Определить глобальные переменные constexpr в анонимном пространстве имен так же, как сделать их встроенными?

В продолжение Почему cppreference определяет ярлыки type_traits xxx_v как встроенный constexpr, а не просто constexpr? Если я создаю свою собственную черту типа и хочу избежать нарушений ODR и хочу, чтобы она была совместима с проектами до C++17, помещает ли ярлык xxx_v в анонимное пространство имен то же самое, что явно объявляет его встроенным?

Например, принимая all_true Из проверки признаков для всех аргументов шаблона переменной, с C++17 я могу написать в заголовке моей утилиты:

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template <bool... v>
inline constexpr bool all_true_v = all_true<v...>::value;

Это то же самое, что написать следующий код, совместимый с pre-C++17?

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
namespace {
   template <bool... v>
   constexpr bool all_true_v = all_true<v...>::value;
}

2 ответа

Решение

Рассматривать

    bool const* g_b= &all_true_v<true>;

это будет иметь тот же адрес в каждой единице перевода для inline constexpr версия, но разные адреса для namespace {} версия.

Вы избегаете нарушения ODR с помощью анонимного пространства имен, так как оно создает новый отдельный набор объектов в каждом файле, в который оно включено. Преимущество inline Объект в том, что будет только один всего.

Однако, если вы используете только constexpr значения как константы, вы не заметите большой разницы. И хороший компилятор может избежать хранения констант в области данных в любом случае.

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

Другие вопросы по тегам