部分专业化问题

时间:2009-01-21 22:36:05

标签: c++

我需要一双新鲜的眼睛。

这显然是非法的,但它显示了我正在尝试做的事情:

template <typename T, T> struct Foo
{
};

template <typename T> struct Foo <T, 0> //Obviously I can't do this.
{
};

有没有办法包装T或做一些棘手的事情以便这种事情可以起作用?

谢谢!

1 个答案:

答案 0 :(得分:14)

是的,你可以使用这个技巧:

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为零。任何条件都可以。作为参考,如果你不使用boost,这里是enable_if的代码。剪切上面的_c后缀,我们不需要以下版本:

template<bool C, typename T = void>
struct enable_if {
  typedef T type;
};

template<typename T>
struct enable_if<false, T> { };