2011-02-01 2 views
8

"C"언어 연결을 사용하는 function-taking-one-argument에 대한 포인터에 대한 템플릿에 public typedef을 추가하려고합니다. 템플릿 내에서 extern- "C"-function 유형을 typedef 할 수 있습니까?

내가 시도 :

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

그리고 :

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

그리고 :

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

을 성공하지.

가능한 것을 달성하려고합니까?

+1

이 모든 것이 'extern'C가 "다른 호출 규칙을 사용할 수도 있습니다"라고 말하면서 문제가 될 수 있지만 거의 발생하지 않을 것입니다. 'extern "C"'가 타입 시스템의 일부가 아니기 때문에, 함수 포인터 타입은이 둘을 구별하지 못한다. 이것은 연결 지정자이다. 즉, * C++에서 만들어진 포인터를 통한 호출은 포인터의 참조가 'extern'C ''인지 여부에 관계없이 작동합니다. 그것은 C에서 호출이 실패 할 수도 있지만, 타입 시스템은 이것을 체크하지 않습니다. –

+3

@ 스티브 : 형식 시스템의 일부입니다. C++ 03 §7.5p1 : "서로 다른 언어 연계가있는 두 가지 함수 유형은 동일하지 않더라도 구별 유형입니다." §5.2.2p1 : "함수 유형이 호출 된 함수 정의의 함수 유형의 언어 연결과 다른 언어 연결을 갖는 표현식을 통해 함수를 호출하는 것은 정의되지 않았습니다." –

+0

@ 프레드 : 오, 오케이. 죄송합니다. 잘못된 정보를 어디에서 골랐는지 모르겠습니다. 또한 함수 포인터를 매개 변수로 사용하는 extern "C"함수를 선언하면 "C"함수 또는 "C++"함수를 사용합니까? 왜냐하면 g ++는 행복하게'-pedantic'을 사용하게합니다. –

답변

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.

불행하게도, 당신은 단순히 ++ 현재 C에서이 작업을 수행 할 수 없습니다. 이 텍스트는 최신 C++ 0x 초안에서 변경되지 않지만 "템플리트 typedef"가이를 수행 할 수 있습니다.

+0

"템플릿 typedef"에 대한 자세한 내용은 어디서 볼 수 있습니까? –

+0

@DanielTrebbien : "템플릿 별칭"이 새 이름 인 것 같습니다. N3225의 §14.5.7과 다양한 논문. –

+0

아니요, 템플릿 별칭으로이 문제가 해결되지 않습니다. C 링키지는 템플리트 유형 별명을 포함하여 템플리트에 적용될 수 없습니다. – bames53

1

boost::function 또는 STL 함수 개체의 typedef을 고려하십시오. 생각해 보면 꽤 명백한 이유로 extern "C"블록 내부에 템플릿을 정의 할 수 없습니다.

+0

@Fred : 템플릿 정의를 extern "C"블록 안에 넣으면 g ++ 4.5.0이 "C 링키지가있는 템플릿"오류를 내 보냅니다. –

+0

이것은 컴파일러에 따라 다를 수 있습니다 ... 내 소스는 http://msdn.microsoft.com/en-us/library/95bhc9c2.aspx – AJG85

+0

@DanielTrebbien : 표준에서 볼 수있는 것은 없습니다 (특히 §7.5에서 보았습니다.), 그것들은 제외되었지만, 모든 컴파일러들이 그것을 거부하는 것처럼 보입니다. (이것은 내 대답에서 인용 한 것을 생각해 볼 때 효과가 없으므로 의미가 있습니다. 그러나 이는 엄격히 금지 된 것과 동일합니다.) –

0

typedef에서 extern "C"을 생략하면 모든 것이 정상적으로 작동하는 것 같습니다. 즉, 경고, 오류 또는 문제없이 다음과 같은 컴파일, 링크 및 실행이다

foo.c를 :

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

Test.cpp에 다음 C++ 전문가 용

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

: 나는 C++과 C 링키지를 구별하는 미세한 점을 모른다. 이와 같은 간단한 예에서 나타나지 않는 숨겨진 문제가 있습니까?

+1

이것은 g ++와 함께 작동합니다. (예 : http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29038 참조) Comeau C/C++ 4.3.10.1에서는 "error : a type of int (\ *) (int) C '를'int (\ *) (int) '유형의 엔티티에 할당 할 수 없습니다. " –

+0

g ++ 4.4.3을 실제로 사용하고 있습니다. – Karmastan

관련 문제