Ошибка 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
:)