Обработка внутренней ошибки компилятора Visual Studio с вложенными шаблонными переменными - PullRequest
5 голосов
/ 30 мая 2019

Я пытаюсь написать код, который позволит мне индексировать типы параметров функции:

template <typename R, typename... ARGS>
R function_return(R(*)(ARGS...));

template <typename R, typename... ARGS>
std::tuple<ARGS...> function_parameters(R(*)(ARGS...));

template <int I, typename T>
using get_type = typename std::conditional_t<(I < 0), std::tuple_element<static_cast<int>(std::tuple_size_v<T>) + I, T>, std::tuple_element<I, T>>::type;

template <int I, typename T>
using parameter_type = get_type<I, decltype(function_parameters(std::declval<T>()))>;

Живой пример (ICE под VS) Пример Live (работает на GCC)

Но когда я пытаюсь использовать это на , я получаю внутренний компиляторошибка:

фатальная ошибка C1001: в компиляторе произошла внутренняя ошибка.

Есть ли другой способ сделать это, который может обойти внутреннюю ошибку компилятора

Ответы [ 2 ]

2 голосов
/ 30 мая 2019

Вероятно, это зависит от точной (под) версии VS2017, так как моя не производит ICE для кода. Тем не менее, код все еще проблематичен, так как он может создавать экземпляр std::tuple_element<2147483647, T> или что-то подобное. Вы должны убедиться, что только правильная ветвь когда-либо оценивается. Замените ваше определение get_type следующим:

template <int I, typename T, bool negative = (I < 0)>
struct get_type_impl;

template <int I, typename T>
struct get_type_impl<I, T, true>
{
  using type = typename std::tuple_element<static_cast<int>(std::tuple_size<T>::value) + I, T>::type;
};

template <int I, typename T>
struct get_type_impl<I, T, false>
{
  using type = typename std::tuple_element<I, T>::type;
};

template <int I, typename T>
using get_type = typename get_type_impl<I, T>::type;

Это работает для меня на моем VS 2017 (кл версия 19.12)

1 голос
/ 30 мая 2019

Как упомянуто здесь , похоже борется с шаблонами, используя операторы, передаваемые друг другу.(Я вижу внутреннюю ошибку компилятора на 15.6.7; так как упоминается здесь , это может быть исправлено исправлениями.)

Я смог обойти это, захватив всефункциональность в одном выражении использования:

template <typename R, typename... ARGS>
R function_return(R(*)(ARGS...));

template <typename R, typename... ARGS>
std::tuple<ARGS...> function_parameters(R(*)(ARGS...));

template <int I, typename T, typename X = decltype(function_parameters(std::declval<T>()))>
using parameter_type = typename std::conditional_t<(I < 0), std::tuple_element<static_cast<int>(std::tuple_size_v<X>) + I, X>, std::tuple_element<I, X>>::type;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...