(Associated with C ++ 0x, How do I extend a tuple into the arguments of a function of a variational matrix?
The following code (see below) is taken from this discussion . The goal is to apply the function to the tuple. I simplified the template parameters and changed the code to get the return value of the generic type.
While the source code compiles fine, when I try to compile the modified code with GCC 4.4.3,
g ++ -std = C ++ 0x main.cc -o main
GCC reports an internal compiler error (ICE) with the following message:
main.cc: In the function 'int main ():
main.cc:53: internal compiler error: in tsubst_copy, cp / pt.c: 10077
Submit a full error report,
with a pre-processed source, if necessary.
See <file: ///usr/share/doc/gcc-4.4/README.Bugs> for instructions.
Question: Is the code correct? or ICE caused by illegal code?
// 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; }
Note. If I rigidly set the return type in the recursive case (see code), then everything will be fine. That is, replacing this fragment with a recursive case does not cause 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...); } };
Alas, this is an incomplete solution to the original problem.