iba*_*bab 5 c++ templates partial-specialization sfinae
我正在尝试使用SFINAE专门为多种类型的结构模板.我知道类似以下的东西:
#include <iostream>
template <typename T, typename Enable = void>
struct S {
void operator()() {
std::cout << "Instantiated generic case" << std::endl;
}
};
template<typename T>
using enabled_type = typename std::enable_if<
std::is_same<T, int>::value ||
std::is_same<T, float>::value
>::type;
template <typename T>
struct S<T, enabled_type<T>> {
void operator()() {
std::cout << "Instantiated int/float case" << std::endl;
}
};
int main() {
S<float>()();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我无法修改S
要添加的结构的主模板typename Enable = void,因为它是外部标头库的一部分.所以主模板必须如下所示:
template <typename T>
struct S {
void operator()() {
std::cout << "Instantiated generic case" << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
有没有办法让我仍然可以使用SFINAE来专门化这个模板?
编辑:请注意,S结构由外部库中的代码使用,因此我必须实际专门化S并且不能将其子类化.此外,我正在处理的真实代码要复杂得多,并且从SFINAE中获益远远超过这个简单的例子(我有多个模板参数需要专门针对多种类型的所有组合).
我有一个坏消息要告诉你:你想要的东西是不可能的。如果主模板没有默认用于void执行操作的额外模板参数enable_if,则无法从最一般的意义上执行此操作。最接近的方法是专门化模板类本身的结构,换句话说:
template <class T>
struct foo {};
template <class T>
struct S<foo<T>> {};
Run Code Online (Sandbox Code Playgroud)
这会起作用。但显然,这不会产生与专门化某些东西(当它与特征匹配时)相同的灵活性。
std::hash您的问题实际上完全等同于尝试专门化满足特征的任何类型的问题。就像您的问题一样,主要类模板定义无法更改,因为它在库代码中,并且库代码实际上hash在某些情况下在内部自动使用专业化,因此无法真正定义新的模板类。
您可以在这里看到类似的问题:Specializing std::hash to衍生类。从类继承是一个很好的例子,它可以表示为特征,但不能表示为模板类。一些知识渊博的 C++ 人员注意到了这个问题,没有人提供比 OP 编写宏来自动消除专业化的解决方案更好的答案。不幸的是,我认为这对您来说也是最好的解决方案。
回想起来,hash也许应该使用第二个模板参数进行声明,该参数默认为 void,以在其他情况下以最小的开销支持此用例。我可以发誓我什至在某个地方看到过关于这个问题的讨论,但我无法追踪它。对于您的库代码,您可能会尝试提出问题以让他们更改。这似乎不是一个重大变化,即:
template <class T, class = void>
struct S {};
template <>
struct S<double> {};
Run Code Online (Sandbox Code Playgroud)
似乎是有效的。
| 归档时间: |
|
| 查看次数: |
1128 次 |
| 最近记录: |