According to the C++ docs, std::copyable_function
has two overloaded ctors as follows:
template<class T, class... CArgs>
explicit copyable_function(std::in_place_type_t<T>,
CArgs&&... args);
template<class T, class U, class... CArgs>
explicit copyable_function(std::in_place_type_t<T>,
std::initializer_list<U> il, CArgs&&... args);
Note that both ctors are required to construct its underlying callable object using direct-non-list-initialization
. Consider the following code:
struct Functor {
Functor(int, int) {
}
Functor(std::initializer_list<int>) {
}
void operator()() const {
}
};
std::copyable_function(std::in_place_type<Functor>, 1, 2)
will call Functor::Functor(int, int)
rather than Functor::Functor(std::initializer_list<int>)
.
If we want to call Functor::Functor(std::initializer_list<int>)
, just use std::copyable_function(std::in_place_type<Functor>, std::initializer_list{1, 2})
.
Both cases are intuitive and no ambiguity. So, my question is:
Why do we need the second ctor while the first one is enough?
{..}
has no types and can only be deduced in few cases:
std::initializer_list<T>
const T(&)[N]
CArgs&&
is not one of them so cannot deduce {1, 2}
as std::initializer_list<int>
The second overload is needed.
You can see yourself with simplified example:
template <typename T>
void foo(T&&) {}
int main() {
foo({1, 2}); // Error
}