我想定义一个提供公共method()
的模板类IE
。method()
调用底层私有run()
,可以接受传递给IE
的模板参数相关的参数。所以:
- 对于
IE<void>
,执行不带参数的run()
。 - 对于
IE<T>
中的任何其他 T,run(vector<T>)
被执行。
我想我正确地 SFINAE 方法run()
,但我在定义应该传递给run
的参数时遇到问题。我想出了以呈现的方式定义Extra
,但我得到了无法推断 T 的错误。
编辑:我需要一个最多适用于C++14的解决方案。
template<typename X=void>
class IE
{
template<typename T=void>
struct Extra;
template<typename T>
struct Extra<enable_if_t<is_void<T>::value, T>> {};
template<typename T>
struct Extra<enable_if_t<!is_void<T>::value, T>>
{
std::vector<T> ex;
};
template<typename X_=X>
void run(enable_if_t<is_void<X_>::value , Extra<X_>> x) {
cout << "In run" << endl;
}
template<typename X_ = X>
void run(enable_if_t<!is_void<X_>::value , Extra<X_>> x)
{
cout << "In run: X=" << x.ex.size() << endl;
}
public:
void method()
{
Extra<X> x;
run(x);
}
};
int main() {
IE<double> ie1;
ie1.method(); // should execute run(vector<double>)
IE<> ie2;
ie2.method(); // should execute run()
return 0;
}
从你的意图来看,你可以用Constexpr来做(从C++17开始(。
template<typename X=void>
class IE
{
void run() {
cout << "In run()" << endl;
}
void run(std::vector<X> x)
{
cout << "In run: X=" << x.size() << endl;
}
public:
template<typename X_ = X>
void method()
{
if constexpr (std::is_same_v<X_, void>)
run();
else
run(std::vector<X_>{...});
}
};
住
在C++17之前,您可以申请SFINAE(或专业化(,例如
template<typename X=void>
class IE
{
void run() {
cout << "In run()" << endl;
}
void run(std::vector<X> x)
{
cout << "In run: X=" << x.size() << endl;
}
public:
template<typename X_ = X>
std::enable_if_t<std::is_same<X_, void>::value> method()
{
run();
}
template<typename X_ = X>
std::enable_if_t<!std::is_same<X_, void>::value> method()
{
run(std::vector<X_>{...});
}
};
住
对于您的原始解决方案,您应该将 SFINAE 应用
template<typename X=void>
class IE
{
template<typename T, typename = void>
struct Extra;
template<typename T>
struct Extra<T, enable_if_t<is_void<T>::value>> {};
template<typename T>
struct Extra<T, enable_if_t<!is_void<T>::value>>
{
std::vector<T> ex;
};
template<typename X_ = X>
enable_if_t<is_void<X_>::value> run(Extra<X_> x) {
cout << "In run" << endl;
}
template<typename X_ = X>
enable_if_t<!is_void<X_>::value> run(Extra<X_> x)
{
cout << "In run: X=" << x.ex.size() << endl;
}
public:
void method()
{
Extra<X> x;
run(x);
}
};
住
这是你对Extra
的定义是不正确的,
您可以简单地将其移出类外并使用常规专业化:
template<typename T>
struct Extra
{
std::vector<T> ex;
};
template<>
struct Extra<void> {};
演示
可能是实际代码更复杂,但对于问题中提出的代码,为IE<void>
提供专用化是最简单的方法。摆脱所有这些enable_if
的东西,并在定义IE
之后添加专业化:
template <>
class IE<void> {
void run() { /* ... */ }
public:
void method() { run(); }
};
(是的,我不喜欢使用constexpr if
来编写具有两个或多个完全独立执行路径的函数,具体取决于某些类型的演算;这太像#ifdef ... #elif ... #endif
了(