GCC ICE - Alternative Function Syntax, Variable Templates, and Tuples

(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.

+4
source share
1 answer

I tried the code in g ++ 4.6. It does not compile due to lack of implementation. However, one way to achieve generality would be to wrap the free-standing function in the std :: function shell and use result_type typedef, as shown below.

 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; } 
+2
source

Source: https://habr.com/ru/post/1309681/


All Articles