vla*_*don 6 c++ templates implicit-conversion template-argument-deduction
非常简化的示例(不必理会类A和运算符在做什么,仅举例来说):
#include <iostream>
using namespace std;
template <bool is_signed>
class A {
public:
// implicit conversion from int
A(int a) : a_{is_signed ? -a : a}
{}
int a_;
};
bool operator==(A<true> lhs, A<true> rhs) {
return lhs.a_ == rhs.a_;
}
bool operator==(A<false> lhs, A<false> rhs) {
return lhs.a_ == rhs.a_;
}
int main() {
A<true> a1{123};
A<false> a2{123};
cout << (a1 == 123) << endl;
cout << (a2 == 123) << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这可行。
但是如果我operator==用模板替换两个(具有相同主体):
template <bool is_signed>
bool operator==(A<is_signed> lhs, A<is_signed> rhs) {
return lhs.a_ == rhs.a_;
}
Run Code Online (Sandbox Code Playgroud)
,其编译会产生错误:
prog.cpp: In function ‘int main()’:
prog.cpp:31:14: error: no match for ‘operator==’ (operand types are ‘A<true>’ and ‘int’)
cout << (a1 == 123) << endl;
~~~^~~~~~
prog.cpp:23:6: note: candidate: ‘template<bool is_signed> bool operator==(A<is_signed>, A<is_signed>)’
bool operator==(A<is_signed> lhs, A<is_signed> rhs) {
^~~~~~~~
prog.cpp:23:6: note: template argument deduction/substitution failed:
prog.cpp:31:17: note: mismatched types ‘A<is_signed>’ and ‘int’
cout << (a1 == 123) << endl;
^~~
Run Code Online (Sandbox Code Playgroud)
可以在这里使用模板吗?我可以以某种方式使用C ++ 17用户定义的模板推导指南吗?还是其他?
在模板参数推导中不考虑隐式转换,这会导致推导is_signed在第二个函数参数上失败。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是重载解析的工作,稍后会发生。
如果您总是operator==在类似 的样式中使用a1 == 123,即 anA<is_signed>始终用作第一个操作数,则可以从推导中排除第二个函数参数。例如
template <bool is_signed>
bool operator==(A<is_signed> lhs, std::type_identity_t<A<is_signed>> rhs) {
return lhs.a_ == rhs.a_;
}
Run Code Online (Sandbox Code Playgroud)
PS:std::type_identity从 C++20 开始支持;即使实现一个也不难。
另一种选择是friend函数,因此函数不是模板,而是使用模板参数:
template <bool is_signed>
class A {
public:
// implicit conversion from int
A(int a) : a_{is_signed ? -a : a}
{}
int a_;
friend bool operator==(const A& lhs, const A& rhs) {
return lhs.a_ == rhs.a_;
}
};
Run Code Online (Sandbox Code Playgroud)