2015-11-05 17 views
20

Ten program wyświetla 1 1 zamiast 1 2 po kompilacji z MSVC (do VS 2015).Błąd ODR w MSVC?

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"; 
} 

To jakby inna Definicje F powodują zerwanie ODR. Ale czy lokalne klasy nie powinny być odrębne? Co ciekawe, jeśli zastąpimy F z funkcjami lambda, nie ma konfliktu.

Czy jest to błąd kompilatora, czy też nie rozumiem zasady jednej definicji?

+0

Bit szalony, że MSVC dostaje coś takiego złego. Nawet się pomyli, jeśli usuniesz 'static' i użyje nienazwanego obszaru nazw. – Simple

+0

Co stanie się, gdy użyjesz dwóch oddzielnych couts zamiast jednego? – cup

+1

Jesteś pewien? W przypadku MSVC 14.0, jeśli 'helper()' zostanie umieszczony w anonimowym obszarze nazw, konflikt zniknie. –

Odpowiedz

1

Jest to oczywiście błąd w MSVC, ponieważ wszystkie typy są unikatowe. Być może dla struktur zdefiniowanych w niektórych funkcjach (w tym przypadku helper) MSVC traktuje je wewnętrznie tak, jakby były zdefiniowane jako helper::F, podczas gdy helper jest statyczny, powinien zrobić coś podobnego do tego f1_cpp::helper::F. W efekcie linker widzi dwie identycznie nazwane funkcje wbudowane i łączy je w jeden.

Najprawdopodobniej poprzez uporządkowanie plików wejściowych można uzyskać 2 2 jeśli nie byli zadowoleni z 1 1 :)

Powiązane problemy