为什么编译器在与转换运算符一起使用时不能推导出模板参数?

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

考虑以下代码:

#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 在上面标记的行编译失败:

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 可转换为 wrapper<int>,所以我预计会发生这种情况。从那里编译器应该能够推断出 Tint。但是不能。

编译器可以正确推断出 std::pair 的模板参数,所以我想知道为什么 wrapper.

不是这种情况

有什么想法吗?

对于 class 模板参数推导,"overload set" 的组成如 [over.match.class.deduct/1] 中所述。这些是:

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.

如你所见,1.1中的匹配"function"只是试图将参数类型完全匹配到模板参数类型。它不考虑转换(很像大多数其他模板推导相关行为)。

它适用于 std::pair 的原因是由于第 1.3 项及其定义的 "copy deduction candidate"。