2014-12-29 10 views
7

Według przykładu której norma przewiduje w N4296::13.3.3 [over.match.best]Dlaczego kompilator nie jest błąd czas rzucony kiedy zadzwonić do funkcji C

namespace A 
{ 
    extern "C" void f(int = 5); 
} 

namespace B 
{ 
    extern "C" void f(int = 5); 
} 

using A::f; 
using B::f; 

void use() 
{ 
    f(3); // OK, default argument was not used for viability 
    f(); // Error: found default argument twice 
} 

jako standard mówi w N4296::7.5/6 [dcl.link]:

dwie deklaracje dla funkcji z łączeniem w języku C o tej samej nazwie funkcji (ignorując nazwy przestrzeni nazw, które ją kwalifikują), że pojawiają się w różnych zakresach przestrzeni nazw, odnoszą się do tej samej funkcji.

próbowałem zbadać coś takiego na własnym przykładzie:

#include <iostream> 

namespace A 
{ 
    extern "C" void foo(int a = 5){ std::cout << a << "1" << std::endl; } 
} 

namespace B 
{ 
    extern "C" void foo(int a = 5); 
} 

using A::foo; 
using B::foo; 

int main() 
{ 
    foo(); //Error 
    foo(2); 
} 

DEMO

Więc dlaczego mój przykład działa? Jakie są różnice między moim przykładem a przykładem Standardu, chyba że zdefiniowałem funkcję jawnie w przestrzeni nazw A? Dlaczego to takie ważne?

+0

Po prostu ciekawi mnie, co jest znaczeniem "extern" C "' funkcji w przestrzeni nazw C++. –

+0

Odp: "Jakie są różnice między moim przykładem a przykładem Standardu, chyba że zdefiniowałem funkcję jawnie w przestrzeni nazw A?": Po prostu próbowałem edytować twoje demo, aby * nie * zdefiniować funkcję jawnie i nadal było dobrze skompilowane. (Łączenie nie powiodło się, oczywiście.) Więc to nie ma znaczenia. Wydaje się, że g ++ po prostu nie daje błędu w tej sytuacji. – ruakh

+0

[Clang też to akceptuje] (http://coliru.stacked-crooked.com/a/2c544e25d8dcdac8). Hmm ... Btw, ważna część specyfikacji brakuje w pytaniu: * "Jeśli najlepsza możliwa do zastosowania funkcja rozwiązuje funkcję, dla której znaleziono wiele deklaracji, i jeśli co najmniej dwa z tych deklaracji - lub deklaracje, do których się odnoszą w przypadku użycia deklaracji - określ domyślny argument, który sprawił, że funkcja była użyteczna, program jest źle sformułowany. "* Brzmi jak wada Clang i g ++? – cdhowie

Odpowiedz

1

Jak już wspomniano w komentarzach, nie ma istotnej różnicy między przykładem standardu a przykładem. Kompilatory, które prawidłowo implementują standard, wydają diagnostykę dla obu.

Fakt, że jest to wyraźnie to błąd kompilatora w co najmniej brzękiem i Intel widać podczas edycji przykład do nonsensowny

namespace A 
{ 
    extern "C" void f(int = 5); 
} 

namespace B 
{ 
    extern "C" void f(int = 3); // different default argument 
} 

using A::f; 
using B::f; 

void use() 
{ 
    f(); // No error ! 
} 

Pomimo coraz dwa różne domyślne argumenty, żadnego błędu ani nawet generowane jest ostrzeżenie. Wykorzystywany jest jeden z domyślnych argumentów: pierwszy z Intelem, drugi z klangiem.

GCC zdarza się odrzucić ten bezsensowny przykład, więc nie ma szybkiej i łatwej metody sprawdzenia, czy jest to oczywiście błąd w GCC, ale nie zmienia to faktu, że jest: jak to podano, po cichu akceptuje przykład ze standardu, w którym standard wskazuje, gdzie należy wykryć błąd.

Powiązane problemy