2009-04-30 37 views
4

在我看来,C++在名称空间和全局作用域(MS VSC++错误C3412)之外的任何作用域中都不允许成员模板专用化。但对我来说,在派生类中专门化一个基类的主成员模板是有意义的,因为那是派生类所做的 - 专用于基类中的事物。例如,考虑下面的例子:成员模板专业化及其范围

struct Base 
{ 
    template <class T> 
    struct Kind 
    { 
     typedef T type; 
    }; 
}; 

struct Derived : public Base 
{ 
    /* Not Allowed */ 
    using Base::Kind; 
    template <> 
    struct Kind <float> 
    { 
    typedef double type; 
    }; 
}; 

int main(void) 
{ 
    Base::Kind<float>::type f; // float type desired 
    Derived::Kind<float>::type i; // double type desired but does not work. 
} 

我的问题是为什么它不被允许?

+1

顺便说一句,在g ++中存在确认错误#39906(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39906),它错误地接受了类似的代码。但是,Comeau和VC++没有。 – Sumant 2009-04-30 18:36:47

回答

4

我明白你想要做什么,但你做得不对。试试这个:

struct Base{}; 
struct Derived{}; 

// Original definition of Kind 
// Will yield an error if Kind is not used properly 
template<typename WhatToDo, typename T> 
struct Kind 
{ 
}; 

// definition of Kind for Base selector 
template<typename T> 
struct Kind<Base, T> 
{ 
    typedef T type; 
}; 

// Here is the inheritance you wanted 
template<typename T> 
struct Kind<Derived, T> : Kind<Base, T> 
{ 
}; 

// ... and the specialization for float 
template<> 
struct Kind<Derived, float> 
{ 
    typedef double type; 
}; 
1

我的问题是为什么它不被允许?

从我的草案的副本,看来下面把上述限制:

在 明确的专业化声明一个类模板,类模板的成员或类成员 模板中,明确专门化的类的名称应该是简单模板标识。

解决方法是专门化封闭类。

1

我会 “忽略” 的标准规范,并尝试逻辑论证:

如果你有两类:

class A 
{ 
    struct S { }; 

}; 

class B: public A 
{ 
    struct S { }; 
}; 

A :: S和B ::小号是两种不同的类型。当您试图通过派生类中的内部类专门化基类中声明的内部类时,实际上是试图定义一个具有相同名称(但另一个命名作用域)的不同类型,从而将逻辑扩展到模板特化。