2010-05-13 3 views
4

(C++0x, How do I expand a tuple into variadic template function arguments? 관련).GCC의 ICE는 - 대체 기능 구문 가변 템플릿 튜플은

다음 코드 (아래 참조)이 discussion로부터 취해진 다. 목적은 튜플에 함수를 적용하는 것입니다. 템플릿 매개 변수를 단순화하고 제네릭 형식의 반환 값을 허용하도록 코드를 수정했습니다.

내가 GCC 4.4.3와 수정 된 코드를 컴파일 할 때 원래의 코드가 잘 컴파일하는 동안,

g++ -std=c++0x main.cc -o main

GCC는 다음과 같은 메시지와 내부 컴파일러 오류 (ICE)보고 :

main.cc: In function ‘int main()’:
main.cc:53: internal compiler error: in tsubst_copy, at cp/pt.c:10077
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.4/README.Bugs> for instructions.

질문 : 코드가 맞습니까? 또는 불법 코드에 의해 유발 된 ICE입니까?

// file: main.cc 
#include <tuple> 

// Recursive case 
template<unsigned int N> 
struct Apply_aux 
{ 
    template<typename F, typename T, typename... X> 
    static auto apply(F f, const T& t, X... x) 
    -> decltype(Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...)) 
    { 
    return Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...); 
    } 
}; 

// Terminal case 
template<> 
struct Apply_aux<0> 
{ 
    template<typename F, typename T, typename... X> 
    static auto apply(F f, const T&, X... x) -> decltype(f(x...)) 
    { 
    return f(x...); 
    } 
}; 

// Actual apply function 
template<typename F, typename T> 
auto apply(F f, const T& t) 
    -> decltype(Apply_aux<std::tuple_size<T>::value>::apply(f, t)) 
{ 
    return Apply_aux<std::tuple_size<T>::value>::apply(f, t); 
} 

// Testing 
#include <string> 
#include <iostream> 

int f(int p1, double p2, std::string p3) 
{ 
    std::cout << "int=" << p1 << ", double=" << p2 << ", string=" << p3 << std::endl; 
    return 1; 
} 

int g(int p1, std::string p2) 
{ 
    std::cout << "int=" << p1 << ", string=" << p2 << std::endl; 
    return 2; 
} 

int main() 
{ 
    std::tuple<int, double, char const*> tup(1, 2.0, "xxx"); 
    std::cout << apply(f, tup) << std::endl; 
    std::cout << apply(g, std::make_tuple(4, "yyy")) << std::endl; 
} 

비고 : 나는 재귀 경우에 반환 유형을 하드 코딩하는 경우 (코드 참조)를 선택한 다음, 모든 것이 괜찮습니다. 즉, ICE 트리거되지 않습니다 재귀 경우에이 조각을 대체한다 :

// Recursive case (hardcoded return type) 
template<unsigned int N> 
struct Apply_aux 
{ 
    template<typename F, typename T, typename... X> 
    static int apply(F f, const T& t, X... x) 
    { 
    return Apply_aux<N-1>::apply(f, t, std::get<N-1>(t), x...); 
    } 
}; 

아아를이 원래 문제에 대한 불완전한 솔루션입니다.

+3

ICE가 발생하지 않아야합니다. 버그를 신고하십시오. – kennytm

+0

버그가 접수되었습니다. GCC Bugzilla 버그 44167 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44167)을 참조하십시오. 건배 –

답변

2

g ++ 4.6에서 코드를 사용해 보았습니다. 누락 된 구현으로 인해 컴파일되지 않습니다. 그러나 일반성을 얻는 한 가지 방법은 독립형 함수를 std :: function 래퍼로 래핑하고 아래와 같이 result_type typedef를 사용하는 것입니다.

template<typename F, typename T> 
typename F::result_type apply(F f, const T& t) 
{ 
    ... 
} 
int f(int p1, double p2, std::string p3) 
{ 
    std::cout << "int=" << p1 << ", double=" << p2 << ", string=" << p3 << std::endl; 
    return 1; 
} 
int main() 
{ 
    std::tuple<int, double, char const*> tup(1, 2.0, "xxx"); 
    std::function<int (int, double, char const *)> func = &f; 
    std::cout << apply(func, tup) << std::endl; 

} 
+0

우아한 솔루션. 불행히도 GCC 4.4.3에서 작동하지 못했습니다. 이유가 확실하지 않습니다. 나는 새로운 것을 찾으면 여기에 올릴거야. 건배 –