(Относится к C ++ 0x, Как расширить кортеж в аргументы функции шаблона variadic? .)
Следующий код (см. Ниже) взят из этого обсуждения . Цель состоит в том, чтобы применить функцию к кортежу. Я упростил параметры шаблона и изменил код, чтобы обеспечить возвращаемое значение универсального типа.
Хотя оригинальный код компилируется нормально, когда я пытаюсь скомпилировать модифицированный код с помощью GCC 4.4.3,
g ++ -std = c ++ 0x main.cc -o main
GCC сообщает о внутренней ошибке компилятора (ICE) со следующим сообщением:
main.cc: в функции int main ():
main.cc:53: внутренняя ошибка компилятора: в tsubst_copy, в cp / pt.c: 10077
Пожалуйста, отправьте полный отчет об ошибке,
с предварительно обработанным источником, если необходимо.
См. для получения инструкций.
Вопрос: Код правильный? или ДВС вызван незаконным кодом?
// 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...);
}
};
Увы, это неполное решение исходной проблемы.