2017-12-13 27 views
2

템플릿을 광범위하게 사용하는 타사 C++ 라이브러리를 다루고 있습니다. 따라서 내 프레임 워크에서 C API를 사용하기가 어렵습니다.런타임 인수로 템플릿 브리징

extern "C" void c_foo(int i); 
extern "C" void c_zoo(int i, int v); 

명백한 구현 될 수있다 :

내가 함수 머리와 C API를 만들

template <int i> void foo(); 
template <int i> void zoo(int v); 

: 문제 추상화

는 라이브러리 기능을 제공합니다 가정

void c_foo(int i) 
{ 
    switch(i) { 
     case 1: foo<1>(); break; 
     case 2: foo<2>(); break; 
     case 3: foo<3>(); break; 
     default: break; 
    }; 
}; 

그리고 void zoo(int)도 마찬가지입니다.

i에 가능한 값의 범위가 작은 경우 제대로 작동합니다. [1,100]에서 i의 가능한 모든 값을 처리하려는 경우 반복이 많으므로이 방법으로 코드를 작성하는 것은 대단히 추악합니다.

코드를 작성하는 방법이 더 간단합니까? 아마도 재귀 전 처리기 매크로를 사용하고 있을까요?

+0

_ "아마도 재귀 전 처리기 매크로 사용?"_ 할 일이 많은 도우미 매크로를 제공하는 여러 라이브러리가 있습니다. 예 : 부스트 전 처리기 lib. – user0042

답변

5

템플릿을 내부적으로 사용하여 필요한 코드를 생성 할 수 있습니다.

이렇게하는 한 가지 방법은 100 개의 함수 포인터로 구성된 디스패치 테이블을 생성 한 다음 런타임에 인덱싱하는 것입니다. c_foo는 도우미를 인덱스의 컴파일 타임 시퀀스를 생성하고 호출합니다 :

extern "C" void c_foo(int i) {  
    c_foo_impl(std::make_integer_sequence<int,100>{}, i); 
} 

디스패치 테이블을 생성하고 호출을 수행합니다이 헬퍼 :

template <int... Is> 
void c_foo_impl (std::integer_sequence<int,Is...>, int i) { 
    constexpr std::array<void(*)(), sizeof...(Is)> dispatch = { &foo<Is>... }; 

    //assert or some other error handling for i > sizeof...(Is) 
    dispatch[i](); 
} 

는 그런 다음 zoo을 위해 동일한 작업을 수행 할 수 있습니다 :

extern "C" void c_zoo(int i, int v) { 
    c_zoo_impl(std::make_integer_sequence<int,100>{}, i, v); 
} 

template <int... Is> 
void c_zoo_impl (std::integer_sequence<int,Is...>, int i, int v) { 
    constexpr std::array<void(*)(int), sizeof...(Is)> dispatch = { &zoo<Is>... }; 

    //assert or some other error handling for i > sizeof...(Is) 
    dispatch[i](v); 
} 

당신이 몇 곳이 필요하다고 생각한다면,이 라이브러리를 추상적 인 세부 사항의 일부 또는 사용할 수있는 등 Petraswitch_table을 제공하여 이러한 종류의 매핑을 수행합니다.

Live demo

+0

나는이 아이디어가 마음에 들지만 디스패치 테이블이 모든 호출마다 다시 생성되는지 궁금하다. 나는 구조체에 포인터 벡터를 포함시키는 약간의 변형을 시도 할 것이라고 생각합니다. 그래서 구조체의 전역 인스턴스를 생성하고 디스 패칭에 사용합니다. – Fabio

+0

'dispatch''를'constexpr'로 만들어 중생을 피할 수 있습니다. – TartanLlama

+0

VS2015에 의해 생성 된 어셈블러는'constexpr'을 사용해도 호출 할 때마다 배열이 다시 초기화된다는 것을 보여줍니다. 문제는 '정적'을 사용하여 사라집니다. – Fabio

0

나는 질문이 템플릿 번호가 무엇인지 추측? 내부 버퍼 크기와 같은 것입니까, 아니면 명령 바이트와 같은 것입니까? 평균 C++ 프로그램은 특정 소수 값만 생성한다고 가정합니다.

아마도 인내심은 일반적인 버퍼 크기 나 명령 이름을 열거하고 인스턴스화하는 것일 수도 있습니다. 따라서 C 코드가 열거 형을 매개 변수로 사용하는 경우 매개 변수로 사용할 수 있습니다. 그렇지 않으면 무시할 수 없습니다.

새로운 항목을 추가하는 것이 정당한 경우 성가심이 있지만 스크립트를 작성할 수 있습니다.

또 다른 접근법은 맹 글링 된 스텁을 생성하는 것입니다. 즉, 아마도 부스트 확장 전 처리기를 사용하여 foo__1() foo__2() 등을 생성하는 것일 수 있습니다. 다시 C 프로그래머는 자동으로 컴파일 타임에 게시 한 메서드와 범위로 제한됩니다.