10

我有一个嵌套在另一个模板中的类模板。部分特化它很容易:我只是template< … >在其父块中声明另一个块。

但是,我需要另一个偏特化来指定其所有本地模板参数。这使它成为一个明确的专业化。无论出于何种原因,显式特化必须在命名空间范围内。要在其父类之外声明它,必须指定父类,这需要一个非空的模板参数列表。这意味着部分专业化。部分专业化我正在做的事情,它应该在任意外部范围内工作。但是 GCC 和 Comeau 都无法使用部分专业化形式参数来识别父提名中的模板参数。

template< class X > struct A {
    template< class Y > struct B; // initial declaration OK

    template< class Z >
    struct B< A< Z > > {}; // partial OK as long as there's a local arg

    template<> // ERROR: this syntax triggers explicit specialization
    struct B< int > {};
};

template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};

(我把我所有的非工作代码都留在了;适当地评论它以试图理解。)

4

4 回答 4

9

在 C++ 标准 14.7.3/18 下是非法的:

.... 如果它的封闭类模板也没有显式特化,则声明不应显式特化类成员模板。

于 2010-01-06T12:41:47.383 回答
4

我倾向于不过多地使用嵌套类。我的主要抱怨是他们倾向于使嵌套类的代码膨胀。

因此,我会提出另一种解决方法:

namespace detail
{
  template <class X, class Z> class BImpl;
  template <class X, class Z> class BImpl<X, A<Z> > {};
  template <class X> class BImpl<X,int> {};
}

template <class X>
class A
{
  template <class Z> struct B: BImpl<X,Z> {};
};

请注意,它需要将 X 作为参数传递给BImpl如果您还想专门化A。有趣的是,在这种情况下,我最终只有部分专业化!

于 2010-01-06T18:11:17.240 回答
0

复杂的东西。你的初始代码 ICE 的 VC10 Beta2,不错。

首先,我认为你有这个倒退:

template<> 
template< class X > 
struct A< X >::B< int > {};

X 是结构 A 的模板参数,而 B 是完全专用的,所以我认为应该是这样的:

template< class X > 
template<> 
struct A< X >::B< int > {};

但即使这样也无法编译。但是,错误文本实际上很有用:

a.cpp a.cpp(11) : 错误 C3212: 'A::B' : 模板成员的显式特化必须是显式特化的成员 a.cpp(8) : 请参阅 'A::B 的声明'

如果您也完全专门化 A,那么完全专门化 B 似乎是合法的。

编辑:好的,我收到了可以对此发表权威言论的人的回复-解释说,这是标准中一个非常模糊的领域,C++ 委员会有一个公开的问题来清理它(“它”是明确的专业化类模板的成员)。在短期内,建议是“不要那样做”。

于 2010-01-06T00:29:31.777 回答
0

至少这在 VC 2010 中有效。但是,我无法编写 def。类声明之外的“int”的fun()。编辑:不幸的是 g++ 也有编译问题。编辑:下面的代码适用于 VC 2010。

template<typename X>
class A
{
public:
    A()
    {

    }

    template<typename Y>
    struct B
    {
        void fun();
    };

    template<>
    struct B<int>
    {
        void fun()
        {
            cout << "Specialized version called\n";
        }
        //void fun();
    };



public:

    B<X> b;
};



template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
    cout << "templated version called\n";
}

int main()
{
   A<int> a;
    a.b.fun();
    A<float> a1;
    a1.b.fun();
}
于 2010-01-06T01:09:08.567 回答