c++ - Why variadic template constructor matches better than copy constructor? -
the following code not compile:
#include <iostream> #include <utility> struct foo { foo() { std::cout << "foo()" << std::endl; } foo(int) { std::cout << "foo(int)" << std::endl; } }; template <typename t> struct bar { foo foo; bar(const bar&) { std::cout << "bar(const bar&)" << std::endl; } template <typename... args> bar(args&&... args) : foo(std::forward<args>(args)...) { std::cout << "bar(args&&... args)" << std::endl; } }; int main() { bar<foo> bar1{}; bar<foo> bar2{bar1}; } compiler error suggest me compiler trying use variadic template constructor instead of copy constructor:
prog.cpp: in instantiation of 'bar<t>::bar(args&& ...) [with args = {bar<foo>&}; t = foo]': prog.cpp:27:20: required here prog.cpp:18:55: error: no matching function call 'foo::foo(bar<foo>&)' bar(args&&... args) : foo(std::forward<args>(args)...) why compiler , how fix it?
this call:
bar<foo> bar2{bar1}; has 2 candidates in overload set:
bar(const bar&); bar(bar&); // args... = {bar&} one of ways determine if 1 conversion sequence better other is, [over.ics.rank]:
standard conversion sequence s1 better conversion sequence standard conversion sequence s2 if
— [...]
— s1 , s2 reference bindings (8.5.3), , types references refer same type except top-level cv-qualifiers, , type reference initialized s2 refers more cv-qualified type reference initialized s1 refers. [ example:int f(const int &); int f(int &); int g(const int &); int g(int); int i; int j = f(i); // calls f(int &) int k = g(i); // ambiguous—end example ]
the forwarding reference variadic constructor better match because reference binding (bar&) less cv-qualified copy constructor's reference binding (const bar&).
as far solutions, exclude candidate set anytime args... should call copy or move constructor sfinae:
template <typename... > struct typelist; template <typename... args, typename = std::enable_if_t< !std::is_same<typelist<bar>, typelist<std::decay_t<args>...>>::value >> bar(args&&... args) if args... 1 of bar, bar&, bar&&, const bar&, typelist<decay_t<args>...> typelist<bar> - , that's case want exclude. other set of args... allowed fine.
Comments
Post a Comment