专门化成员模板而不专门化其父模板

时间:2010-01-05 23:25:13

标签: c++ templates partial-specialization

我有一个嵌套在另一个模板中的类模板。部分特殊化很简单:我只在其父级中声明另一个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 个答案:

答案 0 :(得分:9)

根据C ++标准14.7.3 / 18:

,这是非法的

....声明不应明确专门化一个类成员 模板,如果它的封闭类模板没有明确专门化 同样。

答案 1 :(得分: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> {};
};

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

答案 2 :(得分: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 ++委员会来说是一个公开的问题来清理它(“它”是类模板成员的显式特化)。在短期内,建议是“不要那样做”。

答案 3 :(得分:0)

Atleast这在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();
}
相关问题