Подтвердить что ты не робот

Ошибка 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 на лямбда-функции, конфликт не будет.

Итак, это ошибка компилятора или я не понимаю одно правило определения?

4b9b3361

Ответ 1

Это явно ошибка в MSVC, поскольку все типы уникальны. Возможно, для структур, определенных внутри некоторой функции (в данном случае helper), MSVC внутренне рассматривает их так, как если бы они были определены как helper::F, а если помощник статичен, он должен был сделать что-то вроде этого f1_cpp::helper::F. В результате линкер времени связывает две идентично названные встроенные функции и объединяет их в один.

Скорее всего, переупорядочив входные файлы, вы можете получить 2 2, если вас не устраивает 1 1:)