массив constexpr в заголовке - PullRequest
0 голосов
/ 04 июня 2018

У меня есть следующий код в заголовочном файле, который включен в 2 разных файла cpp:

constexpr int array[] = { 11, 12, 13, 14, 15 };
inline const int* find(int id)
{
    auto it = std::find(std::begin(array), std::end(array), id);
    return it != std::end(array) ? &*it : nullptr;
}

Затем я вызываю find(13) в каждом из файлов cpp.Будут ли оба указателя, возвращаемые find(), указывать на один и тот же адрес в памяти?

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

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

В C ++ 11 и C ++ 14:

В вашем примере array имеет внутреннюю связь (см. [basic.link] /3.2), что означает, что у него будут разные адреса в разных единицах перевода.

И поэтому это нарушение ODR для включения и вызова find в разных единицах перевода (так как его определение отличается).

Простое решение - объявить его extern.

В C ++ 17:

[basic.link]/3.2 изменилось так, что constexpr может быть inline, в этом случае не будет влиять на связь .

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

0 голосов
/ 04 июня 2018

Я не могу претендовать на звание эксперта в этом, но согласно этому сообщению в блоге , ваш код должен делать то, что вы хотите в C ++ 17 ,потому что constexpr тогда подразумевает inline, и эта страница говорит (и я верю этому):

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

Итак, две вещи, которые нужно сделать:

  • убедитесь, что вы компилируете как C ++ 17
  • объявляйте array как constexpr inline, чтобы вызвать ошибку компилятора на старых компиляторах (и убедиться, что вы действительно получаете семантикуВы хотите - см. комментарии ниже)

Я верю, что это сделает.

...