(与
C++0x, How do I expand a tuple into variadic template function arguments?相关)
以下代码(见下文)取自此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...);
}
};
唉,这是原始问题的不完整解决方案.
最佳答案 我试过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;
}