Одно правило определения: могут ли соответствующие объекты иметь разные имена? - PullRequest
2 голосов
/ 28 ноября 2010

Я прочитал и перечитал соответствующие пункты о ODR в стандарте C ++, но этот вопрос все еще остается для меня открытым. Стандарт гласит, что определение встроенной функции должно появляться в каждой единице перевода, в которой она используется, и определения должны быть идентичными в том смысле, который описан почти на странице. В нем говорится, что последовательность токенов должна быть одинаковой. Включает ли он имена локальных идентификаторов?

Другими словами нарушает ли следующая программа ODR? (Я сам пытался протестировать его в Visual Studio 2008 и получил 0 ошибок и 0 предупреждений. Но я полагаю, это не ничего не доказывают, потому что я затем изменил пример на два совершенно разных определения и все еще получил 0 ошибок и 0 предупреждений. В оправдание MSVC следует отметить, что для нарушений ODR формально не требуется никакой диагностики).

//main.cpp
inline int f(int);
int main(){
   f(3);
}
int f(int x){
   int z = x;
   return z*z;
}

//other.cpp
inline int f(int xx){
   int zz = xx;
   return zz*zz;
}

Ответы [ 3 ]

5 голосов
/ 28 ноября 2010

Да, это нарушает ODR.Он использует разные последовательности токенов, я не знаю, что здесь так сложно понять.

Проверка ODR по всем единицам перевода трудна (невозможна) с традиционными методами компиляции.Стандарт гласит: «Диагностика не требуется», поэтому вы просто получаете неопределенное поведение.

При использовании, например, двух разных классов, определенных в несвязанных единицах перевода, но с одинаковым именем, вы можете получить еще более тонкие ошибкиЕсли есть виртуальная таблица, она может конфликтовать без каких-либо сообщений об ошибках (это случилось с моим другом).Так что всегда использует анонимные пространства имен для локальных функций и классов.

3 голосов
/ 28 ноября 2010

Идентификатор является своего рода токеном, каждый идентификатор является отдельным токеном, поэтому да, вам необходимо иметь один и тот же идентификатор для соблюдения ODR. Это может иметь значение в компиляторе, который обнаруживает это (кто-то готов создать пример для como с экспортированным шаблоном - он может обнаружить некоторое нарушение ODR).

Тогда здесь есть разница между C и C ++. C вообще не имеет ODR, и правила для встроенной функции в C99 (в C90 нет встроенных функций) сильно отличаются от C ++. В C99 ваш код правильный. На самом деле вы можете дать совершенно другое определение. Следствием этого является то, что в C (но не в C ++), если вы используете то же определение и это определение имеет статический член, на самом деле у вас столько же статических переменных, сколько и TU, использующих функцию.

2 голосов
/ 28 ноября 2010

Идентификаторы являются токенами, поэтому в соответствии с правилом последовательности токенов программа нарушает ODR.

...