2011-02-02 9 views
20

Jest to kontynuacja pytanie do an answer do Is it possible to typedef a pointer-to-extern-“C”-function type within a template?Dlaczego szablony nie mogą znajdować się w zewnętrznych blokach "C"?

Ten kod nie skompilować z g++, Visual C/C++ i Comeau C/C++ z zasadniczo ten sam komunikat o błędzie:

#include <cstdlib> 

extern "C" { 
    static int do_stuff(int) { 
     return 3; 
    } 

    template <typename return_t_, typename arg1_t_> 
    struct test { 
     static void foo(return_t_ (*)(arg1_t_)) { } 
    }; 
} 

int main() 
{ 
    test<int, int>::foo(&do_stuff); 
    return EXIT_SUCCESS; 
} 

g ++ mówi "błąd: szablon z C linkage", Visual C/C++ emituje błąd kompilatora C2894, a Comeau C/C++ mówi "błąd: ta deklaracja może nie mieć zewnętrznego powiązania" C ".

Chodzi o to, wszyscy są zadowoleni z:

#include <cstdlib> 

extern "C" { 
    static int do_stuff(int) { 
     return 3; 
    } 

    struct test { 
     static void foo(int (*)(int)) { } 
    }; 
} 

int main() 
{ 
    test::foo(&do_stuff); 
    return EXIT_SUCCESS; 
} 

Sekcja 7.5, specyfikacje hydraulika, od C++ standard stwierdza:

A C language linkage is ignored for the names of class members and the member function type of class member functions.

I nawet daje przykład:

extern "C" { 
    class X { 
     void mf(); // the name of the function mf and the member 
       // function's type have C++ language linkage 
     void mf2(void(*)()); // the name of the function mf2 has C++ language 
       // linkage; the parameter has type pointer to C function 
    }; 
} 

Jeśli szablony były dozwolone w zewnętrznych blokach "C", wówczas funkcje członkowskie instancji miałyby C++ l tusz.

Dlaczego więc nie rozdział 14, szablonów z C++ 98, stan normalny:

A template name may have linkage (3.5). A template, a template explicit specialization (14.7.3), and a class template partial specialization shall not have C linkage.

Co to znaczy, że szablon "może" mieć powiązania? Czym jest powiązanie z szablonem?

Dlaczego zabronione jest posiadanie szablonu z łączem C, gdy klasa jest w porządku, a wszystkie funkcje składowe instancji szablonu (domyślny konstruktor, destruktor i przeciążenie operatora przypisania) miałyby powiązanie C++?

+1

Ach, znalazł się na klauzulę, która uniemożliwia szablony mieć powiązania C! –

Odpowiedz

7

What does it mean that a template "may" have linkage? What is template linkage?

Wszystkie nazwy albo mieć powiązania zewnętrzne, wewnętrzne powiązania, albo nie mają powiązania (C++ 03 §3.5p2), ale to nie jest taka sama jak podnośnik języka powiązania. (Mylące, Wiem, C++ 0x znacznie zmienia rzeczy z połączeniem.) Podłączenie zewnętrznego jest wymagany do niczego wykorzystywane jako argument szablonu:

void f() { 
    struct S {}; 
    vector<S> v; // Not allowed as S has internal linkage. 
} 

Zauważmy, że C++ 98 ma „może” w tym, co cytowany z §14p4, ale C++ 03 usuwa „może”, jak Szablony nie mogą zostać uznane w kontekście, który da im wewnętrzną Szkielet:

void f() { 
    // Not allowed: 
    template<class T> 
    struct S {}; 
} 
-4

Ponieważ nie istnieją żadne szablony w C

+10

Nie ma również klas w C, ale dozwolone jest, aby deklaracje klas (i definicje) pojawiały się w zewnętrznym bloku "C". Czemu? –

3

Ponieważ szablon nazwy funkcji muszą być ozdobione dodatkowe informacje, a extern "C" Okazuje dekorację off. Celem extern "C" jest zadeklarowanie funkcji, które można wywołać za pomocą C-link, co oczywiście nigdy nie będzie działać z funkcją szablonu.

+1

Cytowany przykład ze Standardu mówi, że klasa może być zadeklarowana w zewnętrznym bloku "C", a jej funkcje składowe są deklarowane z łączem C++. Jeśli szablon byłby dozwolony, to jego funkcje członkowskie miałyby również powiązanie C++. To "dodatkowa informacja", o której myślę, że się powołujesz. Chyba nie rozumiem, na czym polega różnica. –

+0

@Daniel, nazwy klas nie * trzeba * być dekorowane, ale nazwy szablonów, inaczej w jaki sposób kompilator rozróżniał pomiędzy 'szablonem ' a 'szablonem '? –

13

Szablony nie są faktycznym kodem, są jedynie wytycznymi dla kompilatora, jak wygenerować kod po poznaniu parametrów szablonu. Jako takie nie istnieją, dopóki nie spróbujesz ich użyć. Nie można zapewnić powiązania z czymś, co nie istnieje.

+1

Dlaczego standard C++ wyraźnie zezwala na deklarowanie klas w zewnętrznym bloku "C"? –

+2

@Daniel, zajęcia są konkretne i jednoznaczne. Chociaż metody mogą być nieosiągalne z C, elementy danych mogą być nadal przydatne. –

+2

Elementy danych nie są zniekształcone i nie mają konwencji wywoływania. Standard wyraźnie mówi, że zewnętrzne "C" nie ma do nich zastosowania. Nie rozumiem, jak ich używać tutaj, w sprawach C. –

2

Ponieważ extern C wyłącza nazwa przekręcona który szablony korzystania

Aby zobaczyć, że szablony są realizowane z nazwa przekręcona, kompilacji i dekompilować:

#include <cassert> 

template <class C> 
C f(C i) { return i; } 

int main() { 
    f<int>(1); 
    f<double>(1.5); 
} 

z:

g++ -c -g -std=c++98 main.cpp 
objdump -Sr main.o 

Wyjście zawiera:

int main() { 
    0: 55      push %rbp 
    1: 48 89 e5    mov %rsp,%rbp 
    4: 48 83 ec 10    sub $0x10,%rsp 
    f<int>(1); 
    8: bf 01 00 00 00   mov $0x1,%edi 
    d: e8 00 00 00 00   callq 12 <main+0x12> 
      e: R_X86_64_PC32 _Z1fIiET_S0_-0x4 
    f<double>(1.5); 
    12: 48 b8 00 00 00 00 00 movabs $0x3ff8000000000000,%rax 
    19: 00 f8 3f 
    1c: 48 89 45 f8    mov %rax,-0x8(%rbp) 
    20: f2 0f 10 45 f8   movsd -0x8(%rbp),%xmm0 
    25: e8 00 00 00 00   callq 2a <main+0x2a> 
      26: R_X86_64_PC32 _Z1fIdET_S0_-0x4 
} 
    2a: b8 00 00 00 00   mov $0x0,%eax 
    2f: c9      leaveq 
    30: c3      retq 

Uwaga jak wszyscy callq dokonano zadzwonić imiona dziwne jak _Z1fIiET_S0_.

To samo dotyczy innych funkcji, które zależą od wymieszania nazw, np. przeciążanie funkcji.

Zobacz także: https://stackoverflow.com/a/30526795/895245

Powiązane problemy