(Вопрос об использовании ODR) priority_queue структур с одинаковыми именами в разных файлах - PullRequest
0 голосов
/ 03 октября 2018

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

a.cpp:

#include <queue>

struct Event {  
    int a;
};

static bool operator<(const Event &a, const Event &b) {
    return a.a < b.a;
}

void external_insert(std::priority_queue<Event> &pqu, Event event) {
    pqu.push(event);
}

int main() {
    // fails
    std::priority_queue<Event> pqu;
    external_insert(pqu, Event());

    // works
    // std::priority_queue<Event> pqu;
    // pqu.push(Event());
    return 0;
}

b.cpp:

#include <queue>

struct Event {
    int a, b;
};

static bool operator<(const Event &a, const Event &b) {
    return a.a < b.a;
}

void some_unused_function() {
    std::priority_queue<Event> evqu;
    evqu.push(Event());
}

Затем скомпилируйте эти два файла в два исполняемых файла, используя:

g++ a.cpp b.cpp -o ab
g++ b.cpp a.cpp -o ba

И затем запустите оба с использованием valgrind:

valgrind ./ab
# ... ERROR SUMMARY: 0 errors from 0 contexts ...
valgrind ./ba
# ... ERROR SUMMARY: 2 errors from 2 contexts ...

Точный вывод команды valgrind для двух программ можно найти в this gist .

Не возникает ошибок при выполнении одной из следующих операций:

  • Замена "Event" на любое другое имя в одном из двух файлов
  • Создание обеих структур одинакового размера
  • Выбор второго набора из двух строк в main() вместо первого
  • Замена использования priority_queue на vector и использование push_back вместо push

Я склонен полагать, что это проблема в компиляторе (ошибка компилятора?), Когда именование методов с использованием шаблона для двух версий priority_queue конфликтует друг с другом.

Это известная проблема, это новая ошибка, или я что-то упустил?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Как сказал Джон Цвинк , это нарушение ODR.Вы можете использовать -flto для диагностики таких нарушений:

$ g++ -O2 -flto a.cpp b.cpp 
a.cpp:3:8: warning: type 'struct Event' violates the C++ One Definition Rule [-Wodr]
 struct Event {
        ^
b.cpp:3:8: note: a different type is defined in another translation unit
 struct Event {
        ^
b.cpp:4:12: note: the first difference of corresponding definitions is field 'b'
     int a, b;
            ^
b.cpp:3:8: note: a type with different number of fields is defined in another translation unit
 struct Event {
        ^
0 голосов
/ 03 октября 2018

Вы нарушили правило одного определения, поэтому ваша программа имеет неопределенное поведение.

Чтобы исправить это, вы можете поместить одну или обе структуры в пространство имен, чтобы сделать их уникальными.Если они не нужны вне их собственных файлов .cpp, вы можете поместить их каждый в анонимное пространство имен.

...