c++ - SFINAE:派生类隐藏基类函数依赖于T
问题描述
我编写了 2 个 SFINAE 片段。
他们做同样的事情。
但是,第一个有效,而第二个无效。
为什么?(第二个更类似于我的真实程序。)
此代码有效(http://coliru.stacked-crooked.com/a/50e07af54708f076)
#include <iostream>
#include <type_traits>
enum EN{ EN1,EN2 };
template<EN T1> class B{
public: template<EN enLocal=T1> typename
std::enable_if<enLocal==EN1,void>::type test(){ std::cout<<"1"<<std::endl;}
public: template<EN enLocal=T1> typename
std::enable_if<enLocal==EN2,void>::type test(){ std::cout<<"2"<<std::endl; }
};
int main(){
B<EN1> b;
b.test();
}
但是这段代码是不可编译的(http://coliru.stacked-crooked.com/a/28b6afd443b36c7e):-
#include <iostream>
#include <type_traits>
enum EN{ EN1,EN2 };
class Base{
public: void test(){
std::cout<<"1"<<std::endl;
};
};
template<EN T1> class B : public Base{
public: template<EN enLocal=T1>
std::enable_if_t< enLocal==EN2,void > test(){
std::cout<<"2"<<std::endl;
}
};
int main(){
B<EN1> bEn1; bEn1.test(); //should print 1
//B<EN2> bEn2; bEn2.test(); //print 2
}
我对 SFINAE 非常陌生,并且仍在通过https://stackoverflow.com/a/50562202/学习它。
解决方案
这段代码有两个问题:
- 调用
bEn1.test();
或bEn2.test();
编译器会发现 nametest
指的是类中的函数,B
而重载函数集将仅包含B::test
. 这可以通过将基类中的名称引入派生类来解决:
template<EN T1> class B : public Base{
public: using Base::test;
- 但是,现在非模板函数将优先于模板函数(即使
enable_if
有效),因此B<EN2> bEn2; bEn2.test();
将打印 1。
为了使这项工作再次起作用,您可以引入另一个类似于第一个示例中的重载,它将从基类调用函数,而不是将Base::test
名称带入派生类:
public: template<EN enLocal=T1>
std::enable_if_t< enLocal!=EN2,void > test(){
return Base::test();
}
另一种可能的 C++17 风格的解决方法是使用if constexpr
类型特征或 SFINAE 来代替:
public: template<EN enLocal = T1> void
test()
{
if constexpr(EN2 == enLocal)
{
std::cout<<"2"<<std::endl;
}
else
{
Base::test();
}
}
推荐阅读
- java - 为什么标记为最终或静态的字段未保存在数据库中
- python - Ubuntu 18.04 python 2.7 urllib 请求未获取数据
- python - django:在我的网页中查看 python 脚本的结果
- raspberry-pi - 树莓派零和迷你热敏打印机问题
- swift - spritekit 无法从后台状态打印
- java - 如何在 Kotlin 中将功能接口操作作为参数传递?
- python - 每个服务器前缀
- node.js - 如何在 Windows 中设置 node.js 命令提示符的默认工作目录?
- python - SyntaxError - 冒泡排序
- node.js - 如何在reactJS中初始化未知长度的数组状态?