c++ - 有条件地声明成员函数的简单 SFINAE 问题
问题描述
我已阅读以下主题:
'struct std::enable_if<false, void> 中没有名为 'type' 的类型
但是,我似乎无法在 gcc 和 msvc 上解决这个相当简单的 SFINAE 问题:
#include <type_traits>
#include <iostream>
template<typename A, typename B>
class Test {
public:
template<typename X=A, typename = typename std::enable_if<std::is_same<X, void>::value, void>::type >
void foo() {
std::cout << "A";
}
template<typename X=A, typename = typename std::enable_if<!std::is_same<X, void>::value, void>::type >
void foo() {
std::cout << "B";
}
};
int main(int argc, char **argv) {
Test<int, float> t;
t.foo();
return 0;
}
实际结果:
A = void:完全错误:
main.cpp:15:8: error: 'template<class A, class B> template<class X, class> void Test<A, B>::foo()' cannot be overloaded with 'template<class A, class B> template<class X, class> void Test<A, B>::foo()'
15 | void foo() {
| ^~~
main.cpp:10:8: note: previous declaration 'template<class A, class B> template<class X, class> void Test<A, B>::foo()'
10 | void foo() {
| ^~~
A = int:完全错误:
main.cpp:15:8: error: 'template<class A, class B> template<class X, class> void Test<A, B>::foo()' cannot be overloaded with 'template<class A, class B> template<class X, class> void Test<A, B>::foo()'
15 | void foo() {
| ^~~
main.cpp:10:8: note: previous declaration 'template<class A, class B> template<class X, class> void Test<A, B>::foo()'
10 | void foo() {
| ^~~
main.cpp: In function 'int main(int, char**)':
main.cpp:26:9: error: no matching function for call to 'Test<int, float>::foo()'
26 | t.foo();
| ^
main.cpp:10:8: note: candidate: 'template<class X, class> void Test<A, B>::foo() [with X = X; <template-parameter-2-2> = <template-parameter-1-2>; A = int; B = float]'
10 | void foo() {
| ^~~
main.cpp:10:8: note: template argument deduction/substitution failed:
main.cpp:9:26: error: no type named 'type' in 'struct std::enable_if<false, void>'
9 | template<typename X=A, typename = typename std::enable_if<std::is_same<X, void>::value, void>::type >
| ^~~~~~~~
预期结果
A = void:输出“A”
A = int:输出“B”
我想要的是基于模板参数实现不同的(附加)成员函数。但是,似乎我无法enable_if
依赖类模板类型,但我不知道为什么。根据链接的线程,上面的代码似乎是正确的。你能解释一下为什么这不起作用吗?
解决方案
这是一个 C++17 版本:
template<typename X=A>
std::enable_if_t<std::is_same_v<X, void>> foo() {
std::cout << "A";
}
template<typename X=A>
std::enable_if_t<!std::is_same_v<X, void>> foo() {
std::cout << "B";
}
(默认类型enable_if
是void
用作函数的类型)
您也可以使用constexpr if
:
void foo() {
if constexpr (std::is_same_v<A, void>) {
std::cout << "A";
} else {
std::cout << "B";
}
}
C++11:
template<typename X=A>
typename std::enable_if<std::is_same<X, void>::value>::type foo() {
std::cout << "A";
}
template<typename X=A>
typename std::enable_if<!std::is_same<X, void>::value>::type foo() {
std::cout << "B";
}
推荐阅读
- javascript - PHP/Javascript 动态选择选项 - 如何处理选择选项文本中的撇号问题
- javascript - 如何动态更改输入背景颜色?
- python - 如何使用python在sqlite3中插入字典
- sas - 如何在 sas 数据步骤中获取当前表名?
- c++ - 强制转换和指向 C++ 中的对象语法的指针
- python - 编写具有不同格式(字符串和数字)python的多个数组
- javascript - 使用 JS setTimeout() 时如何传递变量
- java - 如何为不带参数的方法编写单元测试并使用 mongoTemplate 进行查询
- python - 使用python导入格式不正确的txt文件(消除第一行)
- javascript - 为什么以及如何在 `getDerivedStateFromError` 中以这种方式设置状态?