Ошибка ODR в MSVC?
Эта программа печатает 1 1
вместо 1 2
при компиляции с MSVC (до VS 2015).
f1.cpp:
#include <functional>
static std::function<int ()> helper() {
struct F { int operator()() { return 1; } };
return F();
}
std::function<int ()> f1() { return helper(); }
f2.cpp:
#include <functional>
static std::function<int ()> helper() {
struct F { int operator()() { return 2; } };
return F();
}
std::function<int ()> f2() { return helper(); }
main.cpp:
#include <functional>
#include <iostream>
std::function<int ()> f1();
std::function<int ()> f2();
int main() {
std::cout << f1()() << " " << f2()() << "\n";
}
Как будто различные определения F
нарушают ODR. Но разве не должны быть различимы локальные классы? Интересно, что если мы заменим F
на лямбда-функции, конфликт не будет.
Итак, это ошибка компилятора или я не понимаю одно правило определения?
Ответы
Ответ 1
Это явно ошибка в MSVC, поскольку все типы уникальны. Возможно, для структур, определенных внутри некоторой функции (в данном случае helper
), MSVC внутренне рассматривает их так, как если бы они были определены как helper::F
, а если помощник статичен, он должен был сделать что-то вроде этого f1_cpp::helper::F
.
В результате линкер времени связывает две идентично названные встроенные функции и объединяет их в один.
Скорее всего, переупорядочив входные файлы, вы можете получить 2 2
, если вас не устраивает 1 1
:)