Я понимаю, что constexpr
глобалы типа класса практически непригодны, потому что
Такой объект должен быть определен в каждом TU, потому что constexpr
не разрешает предварительное объявление объекта.
Связь по умолчанию как static
приведет к тому, что присвоение имени объекту (использование ODR или нет) во встроенной функции нарушит ODR, потому что соответствующий inline
определения будут иметь разное значение.
Декларация как extern constexpr
одно определение для каждого TU нарушило бы правило ODR, если объект используется ODR, что происходит, когда берется ссылка на него.
this
параметр, даже если он не используется функцией-членом.extern constexpr
даже если не используется ODR.Это все правильно? Есть ли способ иметь constexpr
глобальный тип класса без упаковки его в inline
функционировать?
Глобальные переменные constexpr могут быть безопасно определены ODR в заголовках, используя немного магии макроса и общеизвестный дополнительный уровень косвенности
#define PP_GLOBAL_CONSTEXPR_VARIABLE(type, var, value) \
namespace var##detail { \
template<class = void> \
struct wrapper \
{ \
static constexpr type var = value; \
}; \
template<class T> \
constexpr type wrapper<T>::var; \
} \
namespace { \
auto const& var = var##detail::wrapper<>::var; \
}
Макрос предоставляет ссылку в безымянном пространстве имен
к экземпляру объекта в шаблоне класса реализации.
Каждый объект в безымянном пространстве имен внутри заголовка генерирует
уникальный экземпляр в каждой единице перевода, который включает его заголовок.
Кроме того, для предотвращения нарушений ODR важно, чтобы объекты
например, несколько экземпляров шаблона функции одинаковы.
Тем не менее, для ссылок не имеет значения, что они имеют другую идентичность;
до тех пор, пока они ссылаются на один и тот же экземпляр объекта в реализации
шаблон класса.
Вы можете обернуть этот макрос в заголовок и безопасно включить его во многие TU.
См. Следующее обсуждение в списке рассылки Boost для получения более подробной информации:
http://lists.boost.org/Archives/boost/2007/06/123380.php
Других решений пока нет …