为什么编译器在与转换运算符一起使用时不能推导出模板参数?
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>
,所以我预计会发生这种情况。从那里编译器应该能够推断出 T
是 int
。但是不能。
编译器可以正确推断出 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"。
考虑以下代码:
#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>
,所以我预计会发生这种情况。从那里编译器应该能够推断出 T
是 int
。但是不能。
编译器可以正确推断出 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"。