ODR и внутренняя связь - PullRequest
       51

ODR и внутренняя связь

2 голосов
/ 20 марта 2019

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

// a.cpp
namespace internal {
    int foo(int a) {
        return a+1;
    }
}

int main() {
}

и

// b.cpp
namespace internal {
    int foo(int b) {
        return b+2;
    }
}

Скомпилировав / связав это (g ++ 4.8.3 с -std=c++11), я получаю ошибку

b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'

, что вполне ожидаемо, поскольку, насколько я понимаю, это просто нарушение одно правило определения :

Одно и только одно определение каждой не встроенной функции или переменной, используемой в odr (см. ниже), требуется для отображения во всемПрограмма (включая любые стандартные и пользовательские библиотеки).

Теперь, изменив namespace internal в безымянное пространство имен, ошибка исчезнет.Интуитивно, это имеет смысл для меня, так как я меняю функцию с внешнюю на внутреннюю связь :

Любое из следующих имен, объявленных в области имен, имеет внешнюю связь, если толькопространство имен неименовано или содержится в безымянном пространстве имен (начиная с C ++ 11): переменные и функции, не перечисленные выше (то есть функции, не объявленные статическими [...]) ...

и

[A] Все имена, объявленные в безымянном пространстве имен или в пространстве имен в безымянном пространстве имен, даже если они явно объявлены extern, имеют внутреннюю связь.

Однако я былневозможно найти что-либо в одном правиле определения, которое освобождает от него функции с внутренней связью.Поэтому мой вопрос: правильны ли мои интуитивные рассуждения, или я все еще нарушаю одно правило определения с функциями, которые имеют внутреннюю связь (а компилятор / компоновщик просто больше не сообщает об этом)?Кроме того, где в стандарте (или cppreference.com :)) указано, все ли в порядке?

1 Ответ

2 голосов
/ 20 марта 2019

n4713

§6.5 Программа и связь [basic.link]

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

(2.1) - Когда имя имеет внешнюю связь, к обозначаемому им объекту могут обращаться имена из областей других единиц перевода илииз других областей действия той же единицы перевода.

(2.2) - Когда имя имеет внутреннюю связь, обозначаемая им сущность может именоваться именами из других областей в той же единице перевода.

- Когда имя не имеет связи, обозначаемая им сущность не может именоваться именами из других областей.

Это в основном говорит о том (в случае безымянных пространств имен)имя foo из a.cpp и имя foo из b.cpp каждый относится к разным сущностям.Таким образом, у вас нет двух определений одного и того же объекта, поэтому ODR не нарушается.

...