Должны ли переменные `const` и` constexpr` в заголовках быть `inline` для предотвращения нарушений ODR? - PullRequest
0 голосов
/ 15 декабря 2018

Рассмотрим следующий заголовок и предположим, что он используется в нескольких TU:

static int x = 0;

struct A {
    A() {
        ++x;
        printf("%d\n", x);
    }
};

Поскольку этот вопрос объясняет, что это нарушение ODR и, следовательно, UB.

Теперь, нет нарушения ODR , если наша функция inline ссылается на не-1011 * const объект, и мы не используем его в этой функции (плюс другие условия), так что в заголовке это все еще отлично работает:

constexpr int x = 1;

struct A {
    A() {
        printf("%d\n", x);
    }
};

Но если нам случится использовать его в odr, мы вернемся на круги своя с UB:

constexpr int x = 1;

struct A {
    A() {
        printf("%p\n", &x);
    }
};

Таким образомУчитывая, что теперь у нас есть inline переменных, разве не следует руководствоваться указанием всех namespace переменных в заголовках как inline в заголовках, чтобы избежать всех проблем?

constexpr inline int x = 1;

struct A {
    A() {
        printf("%p\n", &x);
    }
};

Это также, кажется, легче учитьпотому что мы можем просто сказать «inline -все в заголовках» (т.е. определениях функций и переменных), а также «никогда static в заголовках».

Правильно ли это рассуждение?Если да, есть ли какие-либо недостатки в том, чтобы всегда отмечать const и constexpr переменные в заголовках как inline?

1 Ответ

0 голосов
/ 15 декабря 2018

Как вы указали, примеры один и третий действительно нарушают ODR согласно [basic.def.odr] /12.2.1

[..] в каждом определении D соответствующие имена, отыскиваемые в соответствии с [basic.lookup], должны относиться к объекту, определенному в определении D, или к тому же объекту ,после разрешения перегрузки и после совпадения частичной специализации шаблона, за исключением того, что имя может ссылаться на

энергонезависимый объект const с внутренней связью или без нее, если объект

  • не является odr-используется в любом определении D, [..]

Правильно ли это обоснование?

Да, в строкепеременные с внешней связью гарантированно ссылаются на один и тот же объект, даже если они используются odr , пока все определения одинаковы:

[dcl.inline] / 6

Встроенная функция или переменная должны быть определены в каждой единице перевода вкоторый используется в odr и должен иметь одно и то же определение в каждом случае ([basic.def.odr]). [..] Встроенная функция или переменная с внешней связью должны иметь одинаковый адрес во всех единицах перевода.

Последний пример в порядке, потому что он соответствует и не нарушает жирный шрифт вышеупомянутого.

есть ли какие-либо недостатки в том, чтобы всегда отмечать переменные const и constexprв заголовках, как встроенные?

Я не могу придумать ни одного, потому что, если мы сдерживаем обещание иметь точно такое же определение встроенной переменной с внешней связью через TU, компилятор может свободно выбиратьлюбой из них, ссылающийся на переменную, технически будет таким же, как имеющий только один TU и имеющий глобальную переменную, объявленную в заголовке с соответствующими элементами защиты заголовка

...