尽管使用了模板方法,但SFINAE不起作用
SFINAE not working although template methods are used
考虑以下代码,这些代码试图使用SFINAE根据模板参数提供不同的方法实现。
#include <type_traits>
#include <iostream>
template<bool S>
struct C{
template<typename std::enable_if<!S>::type* = nullptr>
int foo(int i){
return i + 1;
}
template<typename std::enable_if<S>::type* = nullptr>
int foo(int i){
return i;
}
};
int main(){
C<true> c1;
C<false> c2;
std::cout << c1.foo(0) << c2.foo(0) << std::endl;
}
这个例子的灵感来源于std::enable_if
的参考页面。如您所见,结构体C<S>
有两个foo
方法。如果S
是true
,则应启用一个,如果S
是false
,则应禁用另一个。但是,该代码不会编译,但会引发以下错误:
src/test.cpp: In instantiation of ‘struct C<true>’:
src/test.cpp:19:12: required from here
src/test.cpp:7:8: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
int foo(int i){
^
src/test.cpp: In instantiation of ‘struct C<false>’:
src/test.cpp:20:13: required from here
src/test.cpp:12:8: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
int foo(int i){
因此,编译器似乎完全忽略了SFINAE,并在发现类型未启用时引发错误。我在这里做错了什么?
S
不是方法的模板参数,它是类的模板参数。在类的实例化过程中,S
已经确定,因此,std::enable_if<!S_>::type
不再依赖于类型,因此不能以您使用它的方式使用。正如Nawaz所回答的,您可以通过使用重载来解决这个问题,但您也可以将S
作为方法的模板参数——有点像:
#include <type_traits>
#include <iostream>
template<bool S>
struct C {
template<bool S_ = S, typename std::enable_if<!S_>::type* = nullptr>
int foo(int i){
return i + 1;
}
template<bool S_ = S, typename std::enable_if<S_>::type* = nullptr>
int foo(int i) {
return i;
}
};
int main(){
C<true> c1;
C<false> c2;
std::cout << c1.foo(0) << c2.foo(0) << std::endl;
}
template<typename std::enable_if<!S>::type* = nullptr>
int foo(int i)
{
return i + 1;
}
这不是函数模板,因为这个(假定(函数模板没有模板参数。它甚至不起作用。代码只是格式不正确。
请注意,S
是封闭类模板的模板参数,而不是函数(template(以下代码是正确的(但不能解决您的问题(:
template<typename SS, typename std::enable_if<!SS>::type* = nullptr>
int foo(int i)
{
//etc
}
这里typename SS
定义了函数模板的模板参数。您的函数没有这样做。std::enable_if
中使用的模板参数必须是相同函数模板的模板参数。
使用函数重载来解决您的问题:
template<bool S>
struct C
{
int foo(int i)
{
return foo_impl(std::integral_constant<bool, S>(), i);
}
private:
int foo_impl(std::true_type, int i)
{
return i + 1;
}
int foo_impl(std::false_type, int i)
{
return i;
}
};
这就是一般性的执行。但在这种特定情况下,当您使用bool
作为模板参数时,另一种解决方案可能是:
template<bool S>
struct C
{
int foo(int i)
{
return S ? foo_a(i) : foo_b(i);
}
private:
int foo_a(int i)
{
return i + 1;
}
int foo_b(int i)
{
return i;
}
};
由于S
是编译器已知的,所以我相信编译器会消除return S ? foo_a(i) : foo_b(i);
中的分支,而是根据S
的值编写return foo_a(i);
或return foo_b(i);
,从而有效地生成更快的代码。
相关文章:
- 我的神经网络不起作用 [XOR 问题]
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- C++为什么尽管我调用了void函数,它却不起作用
- 为什么在保护模式下继承升级不起作用
- 循环在计数器中不起作用
- 在其他文件中创建类时在 c++ 项目中不起作用
- Visual studio代码重构似乎不起作用(例如,重命名符号-f2)
- SFINAE 示例不起作用
- 为什么void_t在SFINAE中不起作用,但enable_if起作用
- 为什么 SFINAE 在这个简单的成员函数重载中不起作用
- 为什么 SFINAE 在这个例子中不起作用?
- 为什么SFINAE在这种情况下不起作用?
- 为什么SFINAE不起作用?
- SFINAE:检测成员变量的存在在 g++ 上不起作用
- 为什么返回Sfinae转换操作员不起作用
- 构造函数上的SFINAE在VC2017中工作,但在clang / gcc中不起作用
- 请帮助我理解为什么SFINAE在这种情况下不起作用
- 为什么 SFINAE 在默认函数参数的右侧不起作用?
- 尽管使用了模板方法,但SFINAE不起作用