использование констант в заголовочном файле с соответствием ODR

Глядя на другой вопрос, я понял, что не могу использовать объекты или функции из анонимного пространства имен через заголовочный файл, поскольку это приведет к нарушениям ODR в определениях классов или встроенных функциях. Если это так, то можно ли безопасно использовать именованные объекты const или constexpr static в inline функциях или классах? Например, если бы CONSTANT было внутри namespace ниже, это было бы небезопасно, но можно ли использовать константу со статической связью?

// some header file to be included by multiple .cpp files
static const/*expr*/ int CONSTANT = 2;

inline int f() {
  return CONSTANT;
}

class Cls {
  int mem = CONSTANT;
};

person Ryan Haining    schedule 14.12.2016    source источник
comment
По крайней мере, в С++ 17 это больше не проблема. Как ни странно, псевдоним типа может решить ваши проблемы: using CONSTANT = std::integral_constant<int, 2>;   -  person Barry    schedule 14.12.2016
comment
@ Барри, как я понимаю, объект не используется odr из цитаты MM, удаленной для C ++ 17?   -  person Ryan Haining    schedule 14.12.2016
comment
N4606 (который является последним черновиком стандарта в соответствии с isocpp.org) все еще имеет объект, который не используется odr   -  person M.M    schedule 14.12.2016
comment
Нет, теперь вы можете просто сделать static constexpr inline CONSTANT = 2;   -  person Barry    schedule 14.12.2016
comment
@Barry Можете ли вы дать ссылку? Вы имели в виду static constexpr inline int CONSTANT = 2;   -  person M.M    schedule 14.12.2016
comment
@MM open-std.org/jtc1/ sc22/wg21/docs/papers/2016/p0386r0.pdf   -  person Ryan Haining    schedule 14.12.2016
comment
Страуструп был недоволен этим iirc   -  person Ryan Haining    schedule 14.12.2016
comment
@RyanHaining согласно этому документу. Функция или переменная, объявленная с помощью спецификатора constexpr, неявно является встроенной функцией или переменной, поэтому inline будет избыточным. Также я не вижу, где изменения в этом документе сделали бы код больше не нарушением ODR.   -  person M.M    schedule 14.12.2016
comment
@M.M извините, не знаю, почему я сначала подумал, что это будет ... жду ответа Барри   -  person Ryan Haining    schedule 14.12.2016
comment
@М.М. Не знаю точных деталей относительно того, какие термины можно опустить. Не помешает добавить все три. И да, пропустил int   -  person Barry    schedule 14.12.2016
comment
@RyanHaining N4606 датирован после этого документа, и часть текста в этом документе отличается от N4606, поэтому мы должны быть осторожны.   -  person M.M    schedule 14.12.2016
comment
@Барри static inline не имеет никакого смысла. Просто inline. И тогда, поскольку у него есть внешняя связь, все случаи использования имени будут относиться к одной и той же переменной.   -  person T.C.    schedule 14.12.2016


Ответы (1)


Этот код в порядке. Полный абзац (C++14 [basic.def.odr/6.2]):

в каждом определении D соответствующие имена, просматриваемые в соответствии с 3.4, должны ссылаться на объект, определенный в определении D, или должны ссылаться на тот же объект после разрешения перегрузки и после сопоставления частичной специализации шаблона, за исключением того, что имя может ссылаться на неизменяемый константный объект с внутренней связью или без нее, если объект имеет один и тот же литеральный тип во всех определениях D, и объект инициализируется константным выражением, и объект не odr-used< /em>, и объект имеет одно и то же значение во всех определениях D; и

Это использование соответствует всем условиям в части "кроме... и... и...":

  • Имя CONSTANT на самом деле относится к энергонезависимому объекту const с внутренней связью.
  • Он имеет один и тот же литеральный тип во всех определениях f().
  • Он инициализируется константным выражением 2.
  • Он не odr-используется.
  • Он имеет одинаковое значение во всех определениях f().

Пункт "Это не odr-используется" должен означать "Это не odr-используется в пределах f()" -- т.е. это не нарушает f(), если вы для odr-использования CONSTANT в другом месте программы.

person M.M    schedule 14.12.2016
comment
Это определенно должно означать, что odr не используется в определении D. - person T.C.; 14.12.2016