Jea*_*ier 29 c++ templates sfinae enable-if c++14
我有以下案例可以使用std::enable_if
:
template<typename T,
typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr>
void f() { }
template<typename T,
typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr>
void f() { }
Run Code Online (Sandbox Code Playgroud)
现在,我在cppreference中看到了新的语法,在我看来更加清晰: typename = std::enable_if_t<std::is_same<int, T>::value>>
我想移植我的代码:
template<typename T,
typename = std::enable_if_t<std::is_same<int, T>::value>>
void g() { }
template<typename T,
typename = std::enable_if_t<std::is_same<double, T>::value>>
void g() { }
Run Code Online (Sandbox Code Playgroud)
但现在海湾合作委员会(5.2)抱怨:
error: redefinition of 'template<class T, class> void g()'
void g() { }
Run Code Online (Sandbox Code Playgroud)
为什么会这样 ?如果可能,我该怎么做才能在这种情况下使用新的,更简洁的语法?
Yak*_*ont 37
我们删除一些代码.
template<
class T,
class U/* = std::enable_if_t<std::is_same<int, T>::value>*/
>
void g() { }
template<
class T,
class U/* = std::enable_if_t<std::is_same<double, T>::value>*/
>
void g() { }
Run Code Online (Sandbox Code Playgroud)
如果编译器拒绝上述两个模板,你会感到惊讶吗?
它们都是"类型"的模板函数template<class,class>void()
.第二种类型参数具有不同的默认值这一事实并不重要.这就像期望两个不同的print(string, int)
函数具有不同的默认int
值来重载.;)
在第一种情况下,我们有:
template<
typename T,
typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr
>
void f() { }
template<
typename T,
typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr
>
void f() { }
Run Code Online (Sandbox Code Playgroud)
在这里我们无法删除该enable_if
条款.更新至enable_if_t
:
template<
class T,
std::enable_if_t<std::is_same<int, T>::value, int>* = nullptr
>
void f() { }
template<
class T,
std::enable_if_t<std::is_same<double, T>::value, int>* = nullptr
>
void f() { }
Run Code Online (Sandbox Code Playgroud)
我还更换了使用的typename
带class
.我怀疑你的困惑是因为typename
有两个含义 - 一个作为一种template
参数的标记,另一个作为依赖类型的消除歧义.
这里第二个参数是一个指针,其类型取决于第一个.编译器无法在没有先替换类型的情况下确定这两者是否存在冲突T
- 并且您将注意到它们实际上永远不会发生冲突.
Okt*_*ist 10
enable_if_t<B>
只是一个别名typename enable_if<B>::type
.让我们替换它,g
以便我们可以看到f
和之间的真正区别g
:
template<typename T,
typename std::enable_if<std::is_same<int, T>::value>::type* = nullptr>
void f() { }
template<typename T,
typename std::enable_if<std::is_same<double, T>::value>::type* = nullptr>
void f() { }
template<typename T,
typename = typename std::enable_if<std::is_same<int, T>::value>::type>
void g() { }
template<typename T,
typename = typename std::enable_if<std::is_same<double, T>::value>::type>
void g() { }
Run Code Online (Sandbox Code Playgroud)
在的情况下f
,我们都与模板参数的两个函数模板<typename, X*>
,其中类型X
是取决于第1模板的类型参数.如果g
我们有两个带有模板参数的函数模板,<typename, typename>
并且它只是依赖的默认模板参数,那么C++认为它们都声明了同一个实体.
这两种样式都可以与enable_if_t
别名一起使用:
template<typename T,
std::enable_if_t<std::is_same<int, T>::value>* = nullptr>
void f() { }
template<typename T,
std::enable_if_t<std::is_same<double, T>::value>* = nullptr>
void f() { }
template<typename T,
typename = std::enable_if_t<std::is_same<int, T>::value>>
void g() { }
template<typename T,
typename = std::enable_if_t<std::is_same<double, T>::value>>
void g() { }
Run Code Online (Sandbox Code Playgroud)