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