c++ - 如果带有模板参数和参数包,如何使用启用?
问题描述
我在使用 c++ 模板时遇到了这段代码,它使用 SFINAE 使用std::enable_if
. 这段代码我面临两个问题。
#include <string>
#include <iostream>
enum class Type : int { First = 1, Second, Third };
template <Type T>
struct Symbol : public std::true_type {
using Parent = std::true_type;
using type = Parent::value_type;
static constexpr type value = Parent::value;
static constexpr type GetValue() {
if constexpr (T == Type::First) return value;
else return !value;
}
};
template <bool b>
using EnableIf = typename std::enable_if<b, int>::type;
template <Type T> static constexpr bool IsTradingSymbol() {
return Symbol<T>::GetValue();
}
template <Type T, EnableIf<IsTradingSymbol<T>()>...>
bool GetErrorForUi(Type A) {
return true;
}
template <Type T, EnableIf<!IsTradingSymbol<T>()>...>
bool GetErrorForUi(Type A) {
return false;
}
int main () {
std::cout << GetErrorForUi<Type::First>(Type::First) << std::endl;
std::cout << GetErrorForUi<Type::Second>(Type::Second) << std::endl;
return 0;
}
1) 为什么在EnableIf<IsTradingSymbol<T>()>...
. 如果我删除...
然后代码在编译中失败。我无法从跟踪中推断出确切的错误,为什么...
那里需要这样做?(使用 GCC 7.4.0 编译)。
enableif.cpp: In function ‘int main()’:
enableif.cpp:43:54: error: no matching function for call to ‘GetErrorForUi<First>(Type)’
std::cout << GetErrorForUi<Type::First>(Type::First) << std::endl;
^
enableif.cpp:26:6: note: candidate: template<Type T, typename std::enable_if<IsTradingSymbol<T>(), int>::type <anonymous> > bool GetErrorForUi(Type)
bool GetErrorForUi(Type A) {
^~~~~~~~~~~~~
enableif.cpp:26:6: note: template argument deduction/substitution failed:
enableif.cpp:43:54: note: couldn't deduce template parameter ‘<anonymous>’
std::cout << GetErrorForUi<Type::First>(Type::First) << std::endl;
^
enableif.cpp:30:6: note: candidate: template<Type T, typename std::enable_if<(! IsTradingSymbol<T>()), int>::type <anonymous> > bool GetErrorForUi(Type)
bool GetErrorForUi(Type A) {
^~~~~~~~~~~~~
enableif.cpp:30:6: note: template argument deduction/substitution failed:
enableif.cpp:43:54: note: couldn't deduce template parameter ‘<anonymous>’
std::cout << GetErrorForUi<Type::First>(Type::First) << std::endl;
^
enableif.cpp:44:56: error: no matching function for call to ‘GetErrorForUi<Second>(Type)’
std::cout << GetErrorForUi<Type::Second>(Type::Second) << std::endl;
^
enableif.cpp:26:6: note: candidate: template<Type T, typename std::enable_if<IsTradingSymbol<T>(), int>::type <anonymous> > bool GetErrorForUi(Type)
bool GetErrorForUi(Type A) {
^~~~~~~~~~~~~
enableif.cpp:26:6: note: template argument deduction/substitution failed:
enableif.cpp:44:56: note: couldn't deduce template parameter ‘<anonymous>’
std::cout << GetErrorForUi<Type::Second>(Type::Second) << std::endl;
^
enableif.cpp:30:6: note: candidate: template<Type T, typename std::enable_if<(! IsTradingSymbol<T>()), int>::type <anonymous> > bool GetErrorForUi(Type)
bool GetErrorForUi(Type A) {
^~~~~~~~~~~~~
enableif.cpp:30:6: note: template argument deduction/substitution failed:
enableif.cpp:44:56: note: couldn't deduce template parameter ‘<anonymous>’
std::cout << GetErrorForUi<Type::Second>(Type::Second) << std::endl;
2) 代码不是用 icc X86-64 (intel compiler 19.0.1) 编译的。编译器不支持std::enable_if
sfinae 还是英特尔编译器本身的错误?
解决方案
1) 为什么在 EnableIf()>.... 中使用参数包。如果我删除 ... 那么代码在编译中会失败。我无法从跟踪中推断出确切的错误,为什么那里根本需要这个……?(使用 GCC 7.4.0 编译)。
看EnableIf<IsTradingSymbol<T>()>
。
这是
template <bool b>
using EnableIf = typename std::enable_if<b, int>::type;
int
当条件为 时也是如此true
,否则没有。
假设条件IsTradingSymbol<T>()
为真;所以
template <Type T, EnableIf<IsTradingSymbol<T>()>...>
bool GetErrorForUi(Type A) {
return true;
}
变得
template <Type T, int ...>
bool GetErrorForUi(Type A) {
return true;
}
现在你有了一个模板函数。它需要一些不可从参数推导出来的参数:a Type
( T
),这是强制性的,以及一个整数列表,零个或多个。
你调用函数如下
GetErrorForUi<Type::First>(Type::First);
所以你传递给函数,作为模板参数,只有一个Type
. 非整数。
这是有效的,因为该函数需要零个或多个整数。
但是当您删除省略号 ( ...
) 时,函数变为
template <Type T, int>
bool GetErrorForUi(Type A) {
return true;
}
现在GetErrorForUi()
期待两个模板参数: aType
和 a int
。完全是一int
,不再是零或更多。
现在一个整数是强制性的,只有一个是可以接受的。
所以现在打电话
GetErrorForUi<Type::First>(Type::First);
不起作用(给出编译错误),因为您没有传递必需的模板int
参数。
并且
GetErrorForUi<Type::First, 0, 1>(Type::First);
不起作用(在省略号删除之后;应该编译之前),因为函数需要一个整数并且您传递了两个int
s。
这也应该回答你的第二点。
推荐阅读
- android - AltBeacon 在很长一段时间后停止扫描
- html - 将 CSS 文件链接到 Hugo 中的部分模板
- python - 使用 OLS 预测双周数据
- c++ - 如何在没有setter的类内部设置类的成员变量?
- mongodb - 将 GraphQL 与 MongoDB 连接时为空
- r - 如何确保输入可以按有状态 LSTM 中的批量大小进行划分?
- uwp - .NET UWP NavigationView.HeaderTemplate TextBlock 从 Frame 中的页面设置
- java - Plivo API 的测试凭证
- apache-spark - Hadoop/Spark:复制因子和性能有什么关系?
- java - BufferedReader 不返回