GCC ICE -- 替代函数语法,可变参数模板和元组

4

(与C++0x,如何将元组扩展为可变模板函数参数?有关。)

以下代码(见下文)摘自此讨论。目标是将函数应用于元组。我简化了模板参数并修改了代码,以允许返回通用类型的返回值。

虽然原始代码可以编译通过,但当我尝试使用GCC 4.4.3编译修改后的代码时,

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

GCC报告了一个内部编译器错误(ICE),并显示以下消息:

main.cc: 在函数 ‘int main()’ 中:
main.cc:53: 内部编译器错误:在 cp/pt.c:10077 的 tsubst_copy 中
如果适当,请提交完整的错误报告和预处理源代码。
有关说明,请参见 <file:///usr/share/doc/gcc-4.4/README.Bugs>。

问题:代码是否正确?还是非法代码触发了内部编译器错误(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
错误已经被记录。请查看GCC Bugzilla Bug 44167 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44167)。干杯! - Marc H.
1个回答

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;

}

优雅的解决方案。不幸的是,我无法在GCC 4.4.3中使其正常工作。我不确定为什么。如果我有新发现,我会在这里发布。干杯。 - Marc H.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接