2016-11-10 4 views
2

Я создал шаблон класса со статическим элементом const. Цель каждой специализации шаблона состоит в том, чтобы иметь свою собственную версию/значение этого статического элемента. Вот мой пример код:Инициализация статической константы для специализации шаблона

template < typename T > class C 
{ 
    public: 
     static const std::string NAME; 
     T something; 
     void printName() { std::cout << NAME << std::endl; } 
}; 

class C1 : public C<int>{}; 
class C2 : public C<char>{}; 

template<> const std::string C<int>::NAME{ "my int" }; // compiles 
template<> const std::string C<char>::NAME{ "my char" }; // compiles 

//template<> const std::string C1::NAME{ "my int" }; // doesn't compile 
//template<> const std::string C2::NAME{ "my char" }; // doesn't compile 

//const std::string C1::NAME{ "my int" }; // doesn't compile 
//const std::string C2::NAME{ "my char" }; // doesn't compile 

int main() 
{ 
    C1 c1; 
    C2 c2; 

    c1.printName(); 
    c2.printName(); 

    std::cout << c1.NAME << " " << c2.NAME << std::endl; 
    std::cout << C1::NAME << " " << C2::NAME << std::endl; 
} 

При использовании компилируемых версий, вывод, что я бы ожидать:

my int 
my char 
my int my char 
my int my char 

Для линий, которые не компилируются, сообщение об ошибке (с помощью GCC 4.4) говорит

ISO C++ does not permit 'C<int>::NAME' to be defined as 'C1::NAME' 

Почему это не разрешено? Я понимаю, что полная специализация шаблона - это класс во всех (?) Уважениях, и этот класс имеет все члены, объявленные в шаблоне. Поэтому я ожидаю, что смогу обратиться к статическим членам этого класса, используя оператор разрешения области. По-видимому, я могу сделать это после инициализации, как в последней строке, указанной выше, но не в самой инициализации.

Может ли кто-нибудь дать представление о том, почему стандарт был написан таким образом? Какие проблемы возникнут, если стандарт допустил синтаксис «bad» выше?

ответ

3

Мне кажется, что проблема, с которой вы сталкиваетесь, не имеет ничего общего с шаблонами. Проблема в том, что вы пытаетесь определить статический член, используя производный класс в вложенном имени-спецификаторе, не в исходном классе. Вы бы тот же вопрос здесь:

struct A { 
    static int x; 
}; 
struct B : A{}; 
int B::x = 42; 

C1 и C2 в вашем коде не являются полными специализаций C, скорее, они являются производными классами специализаций C. Поэтому я не знаю, чего вы ожидаете здесь ...

+0

Это делает вещи более ясными. Я новичок в шаблонах и по-прежнему пытаюсь разобраться в таких концепциях, как создание экземпляров и специализация, и как объединить их с наследованием и т. Д. Давайте посмотрим, есть ли у меня это сейчас: способ, которым я объявил класс C1, компилятор будет генерировать (неявный) экземпляр C , который будет базовым классом для C1. Статический член принадлежит базовому классу, поэтому мне нужно использовать имя базового класса «C » для его инициализации. Аналогично для C2 & C . C и C не имеют отношения наследования; они просто генерируются из одного шаблона. Это верно? – user3065699

+0

Что касается ожидаемого, я хочу, чтобы C1 и C2 (а точнее, их соответствующие базовые классы) имели статический член с именем NAME с разными значениями для каждого (базового) класса. Вот что мне удалось в итоге; Я просто не совсем понял, как это работает. – user3065699

Смежные вопросы