Consider the following code:
#include <utility>
template<typename T>
struct wrapper {
T value;
};
struct foo {
operator wrapper<int>() {
return{10};
}
};
int main() {
foo f;
wrapper w = f; // error
std::pair p = std::make_pair(1, 0); // ok
}
gcc 7.1.1 fails to compile at the marked line above:
main.cpp: In function 'int main()': main.cpp:17:17: error: class template argument deduction failed: wrapper w = f; // error ^ main.cpp:17:17: error: no matching function for call to 'wrapper(foo&)' main.cpp:4:8: note: candidate: template<class T> wrapper(wrapper<T>)-> wrapper<T> struct wrapper { ^~~~~~~ main.cpp:4:8: note: template argument deduction/substitution failed: main.cpp:17:17: note: 'foo' is not derived from 'wrapper<T>' wrapper w = f; // error ^
f
is convertible to wrapper<int>
, so I expect that to happen. From there the compiler should be able to deduce that T
is int
. But it can't.
The compiler can deduce std::pair
's template parameter correctly, so I'm wondering why this isn't the case with the wrapper
.
Any ideas?
For class template argument deduction, the "overload set" is composed as described in [over.match.class.deduct/1] . Those are the following:
A set of functions and function templates is formed comprising:
(1.1) - For each constructor of the primary class template designated by the template-name, if the template is defined, a function template with the following properties:
(1.1.1) - The template parameters are the template parameters of the class template followed by the template parameters (including default template arguments) of the constructor, if any.
(1.1.2) - The types of the function parameters are those of the constructor.
(1.1.3) - The return type is the class template specialization designated by the template-name and template arguments corresponding to the template parameters obtained from the class template.(1.2) - If the primary class template C is not defined or does not declare any constructors, an additional function template derived as above from a hypothetical constructor C().
(1.3) - An additional function template derived as above from a hypothetical constructor C(C), called the copy deduction candidate.
(1.4) - For each deduction-guide, a function or function template with the following properties:
(1.4.1) - The template parameters, if any, and function parameters are those of the deduction-guide.
(1.4.2) - The return type is the simple-template-id of the deduction-guide.
As you can see, the matching "function" in 1.1 only attempts to match the argument types to the template parameter types exactly . It doesn't take conversion into account (much like most other template deduction related behavior).
The reason it works for std::pair
is due to item 1.3, and the "copy deduction candidate" it defines.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.