类模板在类作用域中的特化?

13

为什么在A中S的特化是合法的,而在B中不是?

(如果B没有注释掉) GCC 4.8.1: 错误:‘class B’的非命名空间作用域中存在显式特化

#include <type_traits>
#include <iostream>

class Y {};
class X {};

struct A {
  template<class T, class = void>
  class S;

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };
};

/*
class B
{
    template<class T>
    class S;

    template<>
    class S < Y > {};

    template<>
    class S < X > {};
};
*/


int main()
{
    A::S< X > asd;
    std::cout << asd.i << std::endl;
}

在 coliru 上:B 被注释掉

在 coliru 上:带有 B 的错误


7
你可以在非命名空间范围内进行部分特化,但不能进行显式特化。 - jrok
@jrok,你能详细说明一下吗?这个答案似乎不太正确。这里的回答与之不同。 - Tom De Caluwé
1个回答

13

@jrok的评论基本上解释了您的编译器错误。嵌套类一般而言,特别是嵌套类模板,则是您可以很容易避免的语言中的一个陈旧角落(牢记Sutter的建议:“Write what you know and know what you write”)。

只需创建一个namespace detail来定义您的类模板SASB及其特化,然后在AB内定义一个嵌套模板类型别名S

namespace detail {

  template<class T, class = void>
  class SA;

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };

  template<class T>
  class SB;

  template<>
  class SB < Y > {};

  template<>
  class SB < X > {};
}

struct A
{
    template<class T>
    using S = detail::SA<T>;
};

struct B
{
    template<class T>
    using S = detail::SB<T>;
};

当然,对于这个案例来说可能有些过度,但是如果您想要创建 AB 类模板,并且专门化 AB,那么只有在您还专门化封闭类的情况下才能专门化嵌套类模板。简而言之:通过额外的编译时间接避免这些问题。


我认为使用语句有误,应该像这样写:template using S = detail::SA;参见:http://en.cppreference.com/w/cpp/language/type_alias - Ross Bencina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接