2012-01-08 2 views
3

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

class MyType 
{ 
public: 
    MyType (int a, int b) { } 
}; 

template <class T> 
class MyClass 
{ 
public: 
    static const MyType Type; 
}; 

Инициализирующий тип внутри cpp приведет к ошибке компоновщика. Инициализация типа внутри заголовка приведет к его инициализации несколько раз. Тип инициализации внутри класса не может быть выполнен из-за того, что он не является интегральным типом. Как я могу решить эту проблему без ограничения специализации класса. Любая помощь приветствуется.

+0

«Инициализация типа внутри заголовка приведет к его инициализации несколько раз». Не могли бы вы привести пример того, как вы это делаете? Если вы просто проверяете, вызван ли конструктор более одного раза, его следует вызывать более одного раза, потому что у вас есть один экземпляр для экземпляра класса. – hvd

ответ

3

Я не уверен, что вы подразумеваете под «инициализацией типа внутри cpp, создаст ошибку компоновщика». но предполагая, что вы на самом деле означаете , определяющий, тогда вы, должно быть, сделали что-то неправильно, потому что определение статического члена для каждого типа в соответствующем месте, безусловно, работает! То, что у вас есть в шаблоне класса - это объявление объекта, и это нужно определить где-нибудь, если он когда-либо ссылался. Только если MyType является интегральным типом, вы инициализируете его в своем классе [template], и ​​вам никогда не нужен его адрес (например, привяжите его к постоянной ссылке или возьмите его адрес), вы уйдете, не определяя его. Это потому, что в этом случае он всегда рассматривается как постоянное выражение.

Я предполагаю, что вы пытались определить свой объект что-то вроде этого в некоторых CPP файле:

template <typename T> MyType const MyClass<T>::Type = some-initialization-here; 

Это не будет работать, если вы не инстанцирует это определение явно или неявно в той же единице трансляции. Вы можете определить элемент для конкретного типа что-то вроде этого:

template <> MyType const MyClass<T>::Type = some-initialization-here; 

Если вы на самом деле не нужен тип, чтобы быть постоянным выражением и в этом случае вы можете, как правило, на стороне шаг проблемы, в случае необходимости, что делает его enum (это то, что я, как правило, делать, потому что этот парень может быть привязан к const ссылки, не требуя определения), вы можете использовать статическую функцию-член, который может быть определен в заголовке вместо:

template <typename T> 
MyType const& MyClass<T>::Type() { 
    static MyType rc = some-initialization-here; 
    return rc; 
} 

BTW, I» m довольно уверен, что на этот вопрос был дан ответ, определенно в comp.lang.c++.moderated.

+0

Обратите внимание, что функция по-прежнему заставляет MyClass содержать несколько объектов MyType. Кроме этого, +1. Функция-локальная статика превосходит классовую или глобальную статику просто потому, что у вас нет статического фиаско с порядком инициализации. – Xeo

+0

@Xeo: Ну, конечно: есть один объект за экземпляр. Если вы этого не хотите, вам нужно включить статический член в общий базовый класс [non-templatized]. –

1

Инициализация Тип внутри заголовка приведет к его инициализации несколько раз.

Ну, конечно. Один раз для каждого другого типа, с которым создается MyClass. Это также другой объект для каждого типа, присущий тому, как работают шаблоны. Если вы только хотите, и инициализируется один раз, поместите его в нешаблонном базе:

namespace detail{ 
class MyClassBase{ 
protected: 
    ~MyClassBase(){} // only usable as a base class, non-polymorphic 
    static const MyType Type; // only available to derived types 
}; 
} // detail:: 

template<class T> 
class MyClass 
    : private detail::MyClassBase // private, non-polymorphic 
{ 
public: 
    using MyClassBase::Type; // if you want to expose 'Type' to the public audience 
}; 

Теперь вы можете просто положить

const MyType detail::MyClassBase::Type = /*initialize here*/; 

в .cpp и сделать с ней.


Обратите внимание, что, как правило, лучше, чтобы инкапсулировать static объект внутри функции, так как @Dietmar шоу. Эти функции-локальная статика превосходят любой другой тип статического объекта, потому что вы не будете сталкиваться с фиаско порядка статического инициализации при их использовании.

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