2011-02-01 16 views
8

Chcę dodać publiczny typedef do szablonu dla wskaźnika do funkcji biorących jeden argument, który używa powiązania języka "C".Czy możliwe jest wpisanie w szablonie typu wskaźnik-do-zewnętrznego typu "C"?

Próbowałem:

extern "C" { 
    template <typename return_t_, typename arg1_t_> 
    struct test 
    { 
     typedef return_t_ (*C_fun1_t)(arg1_t_); 
    }; 
} 

oraz:

template <typename return_t_, typename arg1_t_> 
struct test 
{ 
    extern "C" { 
     typedef return_t_ (*C_fun1_t)(arg1_t_); 
    } 
}; 

oraz:

template <typename return_t_, typename arg1_t_> 
struct test 
{ 
    extern "C" typedef return_t_ (*C_fun1_t)(arg1_t_); 
}; 

bez powodzenia.

Czy to, co próbuję osiągnąć, jest możliwe?

+1

Czy to nie to, co sprawia, że ​​całe "zewnętrzne" C "może używać innej konwencji telefonowania", jednej z tych irytujących rzeczy, które musisz wyjaśnić, ale które prawie na pewno nigdy nie będą miały miejsca? Typy wskaźników funkcji nie rozróżniają dwóch, ponieważ 'extern" C "' nie jest częścią systemu typów, jest to specyfikator powiązań. Oznacza to, że wywołania przez wskaźnik wykonany * z C++ * będą działały niezależnie od tego, czy odnośnik wskaźnika jest "zewnętrzny" C ", czy też nie. To wywołania z C, które mogą zawieść, ale system typów nie sprawdza tego dla ciebie. –

+3

@Steve: It * jest * częścią systemu typu; C++ 03 §7.5p1: "Dwa typy funkcji z różnymi powiązaniami językowymi są różnymi typami, nawet jeśli są poza tym identyczne." §5.2.2p1: "Wywołanie funkcji za pomocą wyrażenia, którego typ funkcji ma powiązanie językowe, które różni się od powiązania języka typu funkcji wywołanej definicji funkcji, jest niezdefiniowane." –

+0

@Fred: oh, OK. Niestety, nie jestem pewien, skąd wziąłem te złe informacje. Ponadto, jeśli zadeklaruję zewnętrzną funkcję "C", która sama przyjmie wskaźnik funkcji jako parametr, czy ma funkcję "C" lub funkcję "C++"? Ponieważ g ++ szczęśliwie pozwala mi używać albo z '-pedantic'. –

Odpowiedz

9

C++ 03, §7.5p4:

A linkage-specification shall occur only in namespace scope. … A C language linkage is ignored for the names of class members and the member function type of class member functions.

Niestety, po prostu nie może tego zrobić w bieżącym C++. Ten tekst pozostaje niezmieniony w najnowszym szkicu C++ 0x, ale "szablon typedefs" może być w stanie go wykonać.

+0

Gdzie mogę przeczytać więcej o "szablonie typedefs"? –

+0

@DanielTrebbien: "Aliasy szablonów" wydają się być nową nazwą; §14.5.7 w N3225 plus różne artykuły. –

+0

I nie, aliasy szablonów nie rozwiązują tego problemu. Nie można zastosować powiązania C z szablonami, w tym z aliasami typu szablonu. – bames53

1

Rozważ typedef z obiektu boost::function lub obiektów funkcji STL ... nie można również zdefiniować szablonu wewnątrz zewnętrznego bloku "C" z oczywistych powodów, jeśli się nad tym zastanowić.

+0

@Fred: Kiedy wstawię definicję szablonu do zewnętrznego bloku "C", g ++ 4.5.0 wysyła błąd "szablon z łączem C". –

+0

to może być specyficzny dla kompilatora ... tutaj jest moje źródło http://msdn.microsoft.com/en-us/library/95bhc9c2.aspx – AJG85

+0

@DanielTrebbien: Nie ma nic w standardzie, co mogę zobaczyć (ale szczególnie patrz w §7.5), co wyklucza je, ale wygląda na to, że wszyscy kompilatorzy je odrzucają. (Ma to sens, ponieważ byłoby to nieskuteczne, biorąc pod uwagę to, co cytowałem w mojej odpowiedzi, ale to jest ta sama rzecz, co ściśle zabronione). –

0

Wszystko wydaje się dobrze dla mnie, jeśli po prostu pomijam extern "C" od Twojego typedef. Oznacza to, że poniższe linki, kompiluje i działa bez ostrzeżenia, błędy lub problemy:

foo.c:

#include <stdio.h> 
int foo(int x) { 
    return printf("%x\n", x); 
} 

test.cpp:

extern "C" int foo(int); 

template <typename return_t_, typename arg1_t_> 
struct test 
{ 
    typedef return_t_ (*C_fun1_t)(arg1_t_); 
    C_fun1_t myFn; 
}; 

int main() { 
    test<int, int> t; 
    t.myFn = foo; 
    return t.myFn(5); 
} 

Dla C++ guru: Nie znam dokładniejszych punktów tego, co odróżnia C-link od C++. Czy są jakieś ukryte problemy, które nie pojawią się w prostym przykładzie takim jak ten?

+1

Działa to z g ++ ze względu na znane problem (patrz na przykład http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29038), ale Comeau C/C++ 4.3.10.1 wydaje błąd "błąd: wartość typu int (\ *) (int) C "nie można przypisać do jednostki typu" int (\ *) (int) "" –

+0

Rzeczywiście używam g ++ 4.4.3. – Karmastan

Powiązane problemy