2015-11-05 24 views
20

Questo programma stampa 1 1 anziché 1 2 quando compilato con MSVC (fino a VS 2015).Errore ODR in 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"; 
} 

E 'come se il diverso definizioni di F stanno rompendo ODR. Ma le classi locali non dovrebbero essere distinte? È interessante notare che se sostituiamo F con le funzioni lambda non c'è conflitto.

Quindi questo è un errore del compilatore o sto fraintendendo l'unica regola di definizione?

+0

po 'folle che MSVC ottiene qualcosa di simile a questo torto. È addirittura sbagliato se si rimuove il 'static' e si utilizza uno spazio dei nomi senza nome. – Simple

+0

Cosa succede quando si usano due blocchi separati anziché uno? – cup

+1

Sei sicuro? Con MSVC 14.0, se 'helper()' viene inserito nello spazio dei nomi anonimo, il conflitto sparisce. –

risposta

1

È chiaramente un bug in MSVC, poiché tutti i tipi sono unici. Forse per le strutture definite all'interno di una funzione (in questo caso helper) MSVC le considera internamente come se fossero definite come helper::F mentre se l'helper è statico, dovrebbe invece avere qualcosa di simile a f1_cpp::helper::F. Come risultato al link time linker vede due funzioni inline identiche e le unisce in una.

Molto probabilmente riordinando ingresso file è possibile ottenere 2 2 se non erano soddisfatti 1 1 :)