如何解决 enable_if
的重定义错误¶
Bilibili视频传送门:C++新标准 013 :如何解决 enable_if
的重定义错误
本文从 enablie_if
错误使用,导致编译报错入手,分析错误原因,并给出解决办法
本文的结构如下:
- 错误使用示例
- 错误原因分析
- 解决办法
错误使用示例¶
```c++
include¶
include¶
using namespace std;
class AMyClasss{ public: using size_type = unsigned int; };
class BMyClasss{ public: using size_type = unsigned int; };
//T的类型需要等于 AMyClass
template
//T的类型需要等于BMyClass
template
int main(int argc, char* argv[]) { cout << len(AMyClass()) << endl; cout << len(AMyClass()) << endl; return 0; } ```
本段代码的期待是:如果是 AMyClass 返回 1 , BMyClass 返回 2 。
执行后,报错如下:
error: redefinition of 'template<class T,class> unsigned int len(const T&)'
错误原因分析¶
重定义了默认的模板参数,间接造成了重定义 len
函数。 typename enable_if<is_same<T, BMyClass>::value>::type
最终只是得到个类型。为了分析起来更清晰,简化代码如下:
```c++
template
template
相当于我们定义了同一个 len
函数,却给了两套模板参数默认值。如果用户不设置这个模板参数, C++ 不知道是该调用 int
默认值还是 double
默认值,所以在编译时,会报重复定义的错误。
解决办法¶
使用非类型模板参数,类型已知,值可以是未知的。更改代码如下:
```c++
template
template
在默认情况下, type
相当于 void
,type*
相当于 void*'
,因为用了 enable_if
,可以借助 SFINAE 消除调用时的二义性,解决了在编译时出现的重复定义默认函数的问题。之所以选择 type*
相当于把它当做一个占位符,用来实现 SFINAE 。type
几乎可以是任意类型,默认值 nullptr
也是万能的,可以赋值给任意类型的指针。
当然不一定需要使用指针来做占位符, OneFlow 中例子如下:
c++
template<typename T, typename std::enable_if<!py::detail::is_pyobject<T>::value, int>::type = 0>
使用 int
类型来做占位符,默认值是 0 。对应源码地址, 71 行
更多的例子可以在 OneFlow源码 中搜索