статические типы констант в шаблонных классах - PullRequest
3 голосов
/ 08 января 2012

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

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

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

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

Ответы [ 2 ]

3 голосов
/ 09 января 2012

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

Я предполагаю, что вы пытались определить свой объект примерно так в каком-то файле 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;
}

Кстати, я почти уверен, что на этот вопрос уже был дан ответ, определенно в comp.lang.c ++. Moderated .

1 голос
/ 09 января 2012

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

Ну, конечно. Один раз для каждого другого типа, для которого создается экземпляр 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. Эти статические локальные функции превосходят любые другие типы статических объектов, потому что вы не столкнетесь с фиаско статического порядка инициализации при их использовании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...