如何使用模板函数进行隐式转换

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用户定义的模板推导指南吗?还是其他?

son*_*yao 5

模板参数推导中不考虑隐式转换,这会导致推导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 开始支持;即使实现一个也不难。


Jar*_*d42 5

另一种选择是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)

演示