2014-09-06 6 views
3

난과 같이, 가변-템플릿 기능을 사용하는 라이브러리를 작성하고 기능 설명 같은 : int 인수의 최대 수는 const가 아닌 maxArgs()입니다명시 적 인스턴스화는

template class func<int>; 
template class func<int, int>; 
template class func<int, int, int>; 
// ... 

(이 외부 함수이기 때문에 나는 이것을 변경할 수 없습니다입니다). 나는 다음 시도했다 : 그것은 컴파일에 실패 그래서 컴파일러는 함수 생성 재귀에 적절한베이스 케이스가없는 그러나

template<typename ... T> 
void f(size_t max, T ... args) { // Generates "infinitely" 
    if (sizeof...(T) < max) { 
    func(args...); 
    f(max, args..., 0); 
    } 
} 

int main(int argc, char** argv) { 
    f(maxArgs(), 0); 
    // ... 
    return 0; 
} 

. 나 또한 그렇게 (here에서 몇 가지 코드를 사용하여) 같은 비 형 템플릿을 사용하여 시도했다 :

template<int ...> struct seq { }; 
template<int N, int ... Ns> struct gens : gens<N-1, N-1, Ns...> { }; 
template<int ... Ns> struct gens<0, Ns...> { typedef seq<Ns...> type; }; 

std::vector<int> params; 

template<int ... Ns> 
void f(seq<Ns...>) { 
    test(std::get<Ns>(params)...); 
} 

void instantiate(size_t max) { 
    for (int i = 1; i < max; ++i) { 
    for (int j = 0; j < i; ++j) { 
     params.push_back(0); 
    } 
    f(typename gens<i>::type()); // Fails to compile -- i is not const 
    params.clear(); 
    } 
} 

int main(int argc, char** argv) { 
    instantiate(maxArgs()); 
} 

하지만 그것뿐만 아니라 컴파일에 실패 있도록이는 CONST 값이 필요합니다. maxArgs()의 반환 값을 알지 못해 제대로 수행 할 수 있습니까?

+0

컴파일러 (특히 gcc)는 줄임표와 va_list를 사용하는 C 스타일 가변 인수 함수의 코드 생성을 어떻게 처리합니까? 예를 들면 다음과 같습니다 :'void func (int a, ...) {...}' –

답변

0

maxArgs() (즉 42)에 가능한 최대 값이 있다는 것을 알고 있으므로 @JohnZwinck의 제안 덕분에 다음 해결책을 찾았습니다.

#include <vector> 

typedef void (*void_fnptr)(); 

std::vector<void_fnptr> table; 

// Function that needs to be code-generated for certain number of int types 
template<typename ... T> 
void func(T ... args) { 
    // ... 
} 

template<typename T> 
void instantiate(T elem) { 
    table.push_back((void_fnptr)func<T>); 
} 

template<typename T, typename ... Ts> 
void instantiate(T first, Ts ... rest) { 
    table.push_back((void_fnptr)func<T, Ts...>); 
    instantiate(rest...); 
} 

int main(int argc, char** argv) { 
    // 42 int arguments: 
    instantiate(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); 
    // ... 
    return 0; 
} 
1

아니요, 런타임시에만 알려진 값에 의존하는 컴파일 타임 템플리트에서 생성 할 수 없습니다. 미리 상수 인 최대 값을 선택해야하며, 모든 인스턴스화를 사용하지 않을 수도 있습니다. maxArgs()를 컴파일 타임 상수로 만드는 방법을 찾아야합니다. 또는 사용 중에 즉시 코드를 컴파일하십시오!

이 코드에 대한 정보보다 더 많은 정보가 있기 때문에 실제로 가변적 인 템플릿으로 만들지 여부를 생각할 수 있습니다. 템플릿 인수의 수가 런타임에 결정된다는 점을 감안할 때 그렇지 않을 수 있습니다. variadic 템플릿을 사용하지 않고도 런타임이 완전히 결정되는 솔루션을 작성하는 것이 좋습니다.

+0

이런 식으로 코드를 생성해야하는 이유는 여러 인스턴스에 대해 다른 라이브러리에 함수 포인터를 제공해야하기 때문입니다 어떤 특정 인스턴스가 내 자신의 라이브러리를 사용하는 응용 프로그램에 의해 사용될 것인지를 알지 못하는 func의. 또한 함수 포인터를 전달할 라이브러리가'maxArgs()'를 담당합니다. –

+0

'maxArgs()'의 허용 범위는 무엇입니까? 다른 라이브러리의 정확한 요구 사항은 함수 포인터를 제공하는 방법과 관련하여 무엇입니까? C 스타일 가변 함수 (printf와 같은)에 대한 포인터를 받아 들일 수 있습니까? 아니면 1..maxArgs 인수를 사용하는 일반 함수에 대한 포인터가 필요합니까? 후자의 경우, 그러한 라이브러리가 어떻게 올바르게 사용 되었습니까? 상상하기 힘들 것 같습니다. –

+0

가능한 범위는'8 <= maxArgs() <= 42'입니다. 라이브러리는 함수 포인터 배열 형태로 함수를 취합니다. 여기서 유형은'void (* fn)()'로 타입 캐스트되어야합니다; 함수는 템플릿을 필요로하지 않고 C 스타일 가변 함수를 사용할 수 있습니다. –