简体   繁体   中英

Why can't the compiler deduce the template parameter when used with a conversion operator?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM