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
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With