2011-12-07 4 views
3

작은 C++ 라이브러리의 일부를 C (gcc)로 변환하고 있습니다. 그렇게하면 다음 템플릿 함수를 매크로 (주석을 위해 제거 된 주석)로 변환하려고합니다. CpuReadWriteFence()는 매크로로 성공적으로 변환 한 또 다른 함수입니다.어떻게이 C++ 템플릿 함수를 C 대안으로 변환 할 수 있습니까?

template<typename T> 
static inline T AtomicLoadAcquire(T const* addr) 
{ 
    T v = *const_cast<T const volatile*>(addr); 
    CpuReadWriteFence(); 
    return v; 
} 

C에 템플릿이 없으므로 함수 또는 매크로를 사용하고 있습니다. GCC는 편리한 유형 확장자 인 을 제공합니다. 아마도 나는 void *로 그것을 할 수 있을까? 그렇다면 어떻게? 그 날이 작업을 수행하도록 허용하지 않습니다, 그러나

#define AtomicLoadAcquire(addr)          \ 
    ({ typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence(); }) 

:

int x = AtomicStoreRelease(&bla); 

가 어떻게이 문제를 해결 얻을 것

내가 지금까지 가지고하는 것은 이것이다?

+1

궁금합니다. 왜 C++에서 C로 변환하고 있습니까?참고로 컴파일러가 C1x 기능을 지원하는 경우 [_Generic] (http://en.wikipedia.org/wiki/C1x) 키워드를 사용할 수 있습니다. – iammilind

+0

c1x가 없습니다. 나는이 코드를 C로 작성된 더 큰 무언가에 링크하려고합니다. 실제로 C++ 라이브러리를 끌어 들이고 싶지는 않습니다. 지금이 비트는 C++입니다. – Matt

답변

3

당신은 거의 바로 있어요. GCC "statements and declarations in expressions" 확장 프로그램은 무효화 될 필요가 없습니다.

복합 명령문의 마지막 항목은 세미콜론 다음에 오는 표현식이어야합니다. 이 서브 표현식의 값은 전체 구조의 값으로 사용됩니다. (. 마지막으로 괄호 내에 문의 다른 종류를 사용하는 경우, 구조 무효 입력하지 않으며, 따라서 효과적으로 값있다)

그래서 당신은 당신의 매크로를 정의 할 수 있습니다와 같은 :

#define AtomicLoadAcquire(addr)          \ 
({ typeof (*addr) v = *(volatile typeof (addr))(addr); CpuReadWriteFence(); v; }) 

참고 v; 매크로 끝에. 그것이 마법의 출처입니다.

또한 첫 번째 typeof*addr을 인수로 취하며 volatile typeof(addr) 뒤에 별표가 없습니다. 그것들은 당신의 주된 문제와 관련이없는 사소한 버그들입니다.

+0

+1 이미 사용중인 다른 gcc 확장을 사용할 수도 있습니다! – Nim

+0

Matt H는 이미 ({}) 확장자를 사용하고 있으며, 확장자 전체를 확장하지는 않습니다. – CygnusX1

4

매크로를 사용하여 값을 반환 할 수 없습니다. 이것을 시도하십시오 :

#define AtomicLoadAcquire(addr, ref)          \ 
    ({ typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence(); ref = v; }) 

int x; 
AtomicStoreRelease(&bla, x); // Instead of int x = AtomicStoreRelease(&bla); 
+5

({})은 gcc 특정 트릭입니다. –

0

반환 값을 매크로 매개 변수로 추가 할 수 있습니까? 뭐 그런 :

#define AtomicLoadAcquire(addr, ret)          \ 
    (typeof (addr) v = *(volatile typeof (addr) *)(addr); CpuReadWriteFence();) 

그것은 추한 그러나 이것은 당신을 위해이 작업을 수행합니다

AtomicLoadAcquire(someaddr, x); 

로 번역 :

/* assuming someaddr is int* */ 
int x = *(volatile int *)(someaddr); CpuReadWriteFence(); 
/* now you have x defined */. 

당신이 그것을 원하는대로 정확하게 일 것이다.

기타 옵션 (miaout17에서 언급 한 바와 같이)은 매크로를 호출하기 전에 x을 선언 한 다음 처음에 "typeof(addr)"을 제거하면보다 안전합니다. 매크로의 유형을 전달

0

아마 당신이 할 수있는 최선입니다 :

static inline const volatile void* AtomicLoadAcquire_f(void const* addr) 
{ 
    const volatile void* v = (void const volatile*)addr; 
    CpuReadWriteFence(); 
    return v; 
} 
#define AtomicLoadAcquire(type, pointer) \ 
(*((const volatile type*)AtomicLoadAcquire_f(pointer))) 

int x = AtomicLoadAcquire(int, &bla); 
관련 문제