Может ли встроенная функция в заголовочном файле использовать константу, которая имеет внутреннюю связь?

Рассмотрим следующий код:

const int a = 0;
const std::string b = "hi";

inline void f_a1()
{
    std::cout << a;
}

inline void f_b1()
{
    std::cout << b;
}

inline void f_a2()
{
    std::cout << &a;
}

inline void f_b2()
{
    std::cout << &b;
}

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

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

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

Так как встроенные функции, указанные выше, полагаются на эти константы, какие из этих функций, если таковые имеются, являются правильными?

1 ответ

Решение

Если функция включена в несколько единиц перевода, единственная действующая функция f_a1,

Соответствующим условием является [basic.def.odr]/ 6, в котором говорится, что inline Функция может появляться в нескольких единицах перевода, но только с учетом того, что:

[...] имя может относиться к энергонезависимой const объект с внутренней связью или без связи, если объект имеет одинаковый литеральный тип во всех определениях D, и объект инициализируется с помощью константного выражения (5.19), и объект не используется odr, и объект имеет то же значение в все определения D;

Как объекты constони имеют внутреннюю связь в [basic.link]/ 3:

Имя, имеющее область имен (3.3.6), имеет внутреннюю связь, если это имя [...]
- энергонезависимая переменная, которая явно объявлена ​​как const или constexpr и ни явно не объявлена ​​как extern, ни ранее объявлена ​​как имеющая внешнюю связь [...]

Однако получение адреса или формирование ссылки на переменную (например, для передачи аргумента) - это использование odr, поэтому f_a2 а также f_b2 являются недействительными f_b1 также недействителен, так как ostream оператор вывода для std::string принимает аргумент по ссылке; и даже если он принимает свой аргумент по значению, неявно вызываемый конструктор копирования будет принимать его аргумент по ссылке. f_a1 все в порядке, потому что int оператор stream-out принимает аргумент по значению и копирует значение int const это не odr-использование.

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