Стандарт с ++: есть ли внутренняя связь переменных constexpr с областью имен?

Представьте, что у нас есть заголовок foo.h, содержащий следующее:

#ifndef FOO_H_
#define FOO_H_

namespace foo {
constexpr std::string_view kSomeString = "blah";
}

#endif  // FOO_H_

Гарантируется ли foo::kSomeString наличие внутренней ссылки в любой единице перевода, которая включает foo.h? Различается ли это между C ++ 11 и C ++ 17?

В проекте стандарта [basic.link] / 3 говорится

Имя, имеющее область пространства имен, имеет внутреннюю связь, если это имя [...] не встроенной переменной энергонезависимого константного типа, которая не была явно объявлена ​​как extern и ранее не была объявлена ​​как имеющая внешнюю связь [...]

Но я не знаю, считается ли constexpr "квалифицированным с учетом констант". Это где-то сказано в стандарте?

Предполагая, что это гарантированно имеет внутреннюю привязку, похоже, что не может быть проблем с ODR для этого использования, верно? (В отличие от того, что написано в этом ответе.)


person jacobsa    schedule 08.09.2017    source источник
comment
Да, constexpr в объявлениях подразумевает const в C ++ 11. В C ++ 14 и выше он подразумевает const только для переменных, но не для функций-членов.   -  person Kerrek SB    schedule 08.09.2017
comment
Спасибо! Вы знаете, в каком разделе стандарта это сказано?   -  person jacobsa    schedule 08.09.2017


Ответы (2)


Да, constexpr в объявлении объекта означает, что это const. См. [dcl.constexpr] / 9. И да, это означает, что kSomeString в вашем примере имеет внутреннюю связь.

Вид нарушения ODR, о котором мы говорим здесь, - это не определение самого kSomeString, а другие определения, которые пытаются его использовать. И проблема именно из-за внутренней привязки. Учитывать:

void f(const std::string_view &);

inline void g() { 
    f(foo::kSomeString); 
}

Это нарушение ODR, если оно включено в несколько единиц трансляции, по существу потому, что определение g в каждой единице трансляции ссылается на другой объект.

person T.C.    schedule 08.09.2017
comment
Спасибо! Ваш пример проблем ODR имеет смысл - g не одинаков в каждой единице перевода. Возможны ли проблемы, не связанные со встроенными функциями? - person jacobsa; 08.09.2017
comment
@jacobsa: другой очевидный пример - шаблоны, принимающие не типовые параметры. - person Martin Bonner supports Monica; 11.04.2018
comment
@ T.C., Боюсь, я не совсем согласен с вами, пожалуйста, взгляните на мой ответ. - person neonxc; 06.03.2019

Ваше использование kSomeString совершенно верно.

Перво-наперво; ваш объект квалифицируется как const, так как T.C. объяснил. Кроме того, он имеет буквальный тип, поскольку имеет конструктор constexpr. Поэтому, если вы используете его в функции, определенной в файле заголовка, в стандарте применяется следующее исключение (глава 3.2):

В программе может быть более одного определения встроенной функции с внешней связью (7.1.2), шаблона нестатической функции (14.5.6), (…) при условии, что каждое определение появляется в разных единицах перевода и при условии определения удовлетворяют следующим требованиям. Если такая сущность с именем D определена более чем в одной единице перевода, то

  • каждое определение D должно состоять из одной и той же последовательности токенов; и
  • в каждом определении D соответствующие имена, найденные в соответствии с 3.4, должны относиться к объекту, определенному в определении D, или должны относиться к тому же объекту после разрешения перегрузки (13.3) и после сопоставления частичной специализации шаблона (14.8 .3), за исключением того, что имя может относиться к константному объекту с внутренней связью или без нее, если объект имеет тот же буквальный тип во всех определениях D, и объект инициализирован константным выражением (5.19), и используется значение (но не адрес) объекта, и объект имеет одно и то же значение во всех определениях D;
  • (…)
person neonxc    schedule 06.03.2019
comment
и используется значение (но не адрес) объекта. При связывании ссылки используется ее адрес. - person T.C.; 06.03.2019
comment
@ T.C. Вы правы, но я не ошибаюсь :). Я не поощрял брать его адрес. Я согласен, что ваше конкретное использование является ловушкой, но хотел бы отметить, что использование такого объекта в общем определении в целом не является неправильным. - person neonxc; 06.03.2019