GCC ICE - альтернативный синтаксис функции, вариационные шаблоны и кортежи - PullRequest
4 голосов
/ 13 мая 2010

(Относится к 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...);
  }
};

Увы, это неполное решение исходной проблемы.

1 Ответ

2 голосов
/ 15 мая 2010

Я пробовал код на 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;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...