【发布时间】:2009-01-21 22:36:04
【问题描述】:
我需要一双新鲜的眼睛。
这显然是非法的,但它显示了我正在尝试做的事情:
template <typename T, T> struct Foo
{
};
template <typename T> struct Foo <T, 0> //Obviously I can't do this.
{
};
有没有什么方法可以包装 T 或做一些棘手的事情以便这种事情可以工作?
谢谢!
【问题讨论】:
标签: c++
我需要一双新鲜的眼睛。
这显然是非法的,但它显示了我正在尝试做的事情:
template <typename T, T> struct Foo
{
};
template <typename T> struct Foo <T, 0> //Obviously I can't do this.
{
};
有没有什么方法可以包装 T 或做一些棘手的事情以便这种事情可以工作?
谢谢!
【问题讨论】:
标签: c++
是的,你可以使用这个技巧:
template <typename T, T, T=0> struct Foo {
};
template <typename T, T t> struct Foo <T, t, t> {
};
如果特化中 t 为 0,它将匹配默认参数,并采用特化。否则,将采用主模板。
编辑:第三个参数到底是什么意思?嗯,它是一个默认值,它是 0。例如,当我们将专业化命名为 Foo<int, 5> 时,它将被传递。但实际上,我们使用参数Foo<int, 5, 0> 实例化了一个模板,因为最后一个参数是默认参数。偏特化匹配,当第三个参数匹配第三个参数时,默认为零,如果第三个和第二个参数相同,因为都是t。
上述技巧的缺点是Foo<int, 9, 9> 也使用了我们的特化。但另一方面,上述内容非常简单,因此您可能会逃脱惩罚。如果你不希望它工作,那么你可以使用enable_if,这有点复杂:
template <typename T, T, typename = void> struct Foo {
};
template <typename T, T t>
struct Foo <T, t, typename boost::enable_if_c< t == 0 >::type> {
};
现在,即使您说Foo<int, 9, void>,也不会选择我们的部分特化,因为条件t == 0 不正确,因此::type 将不可用。 SFINAE当时没有选择专业化。当然,使用此 enable_if 解决方案,您不仅限于 t 为零。任何条件都可以。作为参考,这里是 enable_if 的代码,如果你不使用 boost。把上面的_c后缀剪掉,下面的版本就不需要了:
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
【讨论】: