MS Visual Studio 2017 上的 Variadic 模板编译问题
Variadic template compilation issue on MS Visual Studio 2017
我需要一个模板来找出 class 从其基类及其索引继承的类型顺序。该代码适用于 clang 和 gcc,但在目标环境 Visual Studio 中,我收到内部编译器错误 "fatal error C1001: An internal error has occurred in the compiler."。我正在寻找一些解决方法或者可能是我的代码中的错误。是的,我已经试过了 google.
提前致谢。
#include <type_traits>
#include <iostream>
struct BaseA
{
};
struct BaseB
{
};
struct BaseC
{
};
template <class... Types>
class type_list {};
template<typename Type, typename TypeList>
struct get_idx_for_type;
template<typename Type, template<typename...> typename TypeList, typename ...Types>
struct get_idx_for_type<Type, TypeList<Types...>>
{
template<int I, typename T, typename ...Rest>
struct find_type;
template<int I, typename T, typename U, typename ...Rest>
struct find_type< I, T, U, Rest... >
{
// problematic line for compiler, problem is somewhere in find_type recursion
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, Rest...>::value;
};
template<int I, typename T, typename U>
struct find_type< I, T, U >
{
static constexpr int value = std::is_same<T, U>::value ? I : -1;
};
static constexpr int value = find_type<0, Type, Types...>::value;
};
template<typename ...Bases>
struct Foo : public Bases...
{
using base_types_list = type_list<Bases...>;
};
int main()
{
using T = Foo<BaseA, BaseB, BaseC>;
Foo<BaseA, BaseB, BaseC> q;
int a = get_idx_for_type<BaseA, T::base_types_list>::value;
std::cout << a << std::endl;
return 0;
}
I'm getting an internal compiler error "fatal error C1001: An internal error has occurred in the compiler.".
所以,我想,你的代码是正确的,但编译器有问题。
I'm looking for some workaround or maybe an error in my code.
我没有你的编译器,所以这是在黑暗中拍摄,但我建议使用另一个专业化(U
和 [=13= 的专业化)重写你的 find_type
结构] 是同一类型;U
和 T
的特化不同)并从 std::integral_constant
.
继承 value
所以我提出以下建议
template <int, typename ...>
struct find_type;
template <int I, typename T>
struct find_type<I, T> : public std::integral_constant<int, -1>
{ };
template <int I, typename T, typename ... Rest>
struct find_type<I, T, T, Rest...> : public std::integral_constant<int, I>
{ };
template <int I, typename T, typename U, typename ... Rest>
struct find_type<I, T, U, Rest...> : public find_type<I+1, T, Rest...>
{ };
内部编译器错误始终是编译器中的错误,无论是否存在
你的代码有什么问题吗?要解决这个问题,您可以替换:
template<int I, typename T, typename U, typename ...Rest>
struct find_type< I, T, U, Rest... >
{
// problematic line for compiler, problem is somewhere in find_type recursion
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, Rest...>::value;
};
与:
template<int I, typename T, typename U, typename V, typename ...Rest>
struct find_type< I, T, U, V, Rest... >
{
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, V, Rest...>::value;
};
协助 VC++ 消除歧义:
template<int I, typename T, typename U>
struct find_type< I, T, U >
{
static constexpr int value = std::is_same<T, U>::value ? I : -1;
};
当 ...Rest
为空时。
另一种可能的替代方法是通过模板函数,而不是 find_type
结构。
举个例子...如果你定义一个static constexpr
方法find_type_func()
如下(C++17,但如果你愿意,我可以很容易地将它改编成C++14)
template <typename T, typename ... List>
constexpr static int find_type_func ()
{
int ret { -1 };
int i { 0 };
((ret = (ret == -1) && std::is_same<T, List>{} ? i : ret, ++i), ...);
return ret;
}
你可以删除struct find_type
并初始化value
如下
static constexpr int value = find_type_func<Type, Types...>();
-- 编辑--
如所问,C++14版本
template <typename T, typename ... List>
constexpr static int find_type_func ()
{
using unused = int[];
int ret { -1 };
int i { 0 };
(void)unused { 0, (std::is_same<T, List>::value ? ret = i : ++i)... };
return ret;
}
我需要一个模板来找出 class 从其基类及其索引继承的类型顺序。该代码适用于 clang 和 gcc,但在目标环境 Visual Studio 中,我收到内部编译器错误 "fatal error C1001: An internal error has occurred in the compiler."。我正在寻找一些解决方法或者可能是我的代码中的错误。是的,我已经试过了 google.
提前致谢。
#include <type_traits>
#include <iostream>
struct BaseA
{
};
struct BaseB
{
};
struct BaseC
{
};
template <class... Types>
class type_list {};
template<typename Type, typename TypeList>
struct get_idx_for_type;
template<typename Type, template<typename...> typename TypeList, typename ...Types>
struct get_idx_for_type<Type, TypeList<Types...>>
{
template<int I, typename T, typename ...Rest>
struct find_type;
template<int I, typename T, typename U, typename ...Rest>
struct find_type< I, T, U, Rest... >
{
// problematic line for compiler, problem is somewhere in find_type recursion
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, Rest...>::value;
};
template<int I, typename T, typename U>
struct find_type< I, T, U >
{
static constexpr int value = std::is_same<T, U>::value ? I : -1;
};
static constexpr int value = find_type<0, Type, Types...>::value;
};
template<typename ...Bases>
struct Foo : public Bases...
{
using base_types_list = type_list<Bases...>;
};
int main()
{
using T = Foo<BaseA, BaseB, BaseC>;
Foo<BaseA, BaseB, BaseC> q;
int a = get_idx_for_type<BaseA, T::base_types_list>::value;
std::cout << a << std::endl;
return 0;
}
I'm getting an internal compiler error "fatal error C1001: An internal error has occurred in the compiler.".
所以,我想,你的代码是正确的,但编译器有问题。
I'm looking for some workaround or maybe an error in my code.
我没有你的编译器,所以这是在黑暗中拍摄,但我建议使用另一个专业化(U
和 [=13= 的专业化)重写你的 find_type
结构] 是同一类型;U
和 T
的特化不同)并从 std::integral_constant
.
value
所以我提出以下建议
template <int, typename ...>
struct find_type;
template <int I, typename T>
struct find_type<I, T> : public std::integral_constant<int, -1>
{ };
template <int I, typename T, typename ... Rest>
struct find_type<I, T, T, Rest...> : public std::integral_constant<int, I>
{ };
template <int I, typename T, typename U, typename ... Rest>
struct find_type<I, T, U, Rest...> : public find_type<I+1, T, Rest...>
{ };
内部编译器错误始终是编译器中的错误,无论是否存在 你的代码有什么问题吗?要解决这个问题,您可以替换:
template<int I, typename T, typename U, typename ...Rest>
struct find_type< I, T, U, Rest... >
{
// problematic line for compiler, problem is somewhere in find_type recursion
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, Rest...>::value;
};
与:
template<int I, typename T, typename U, typename V, typename ...Rest>
struct find_type< I, T, U, V, Rest... >
{
static constexpr int value = std::is_same<T, U>::value ? I : find_type<I + 1, T, V, Rest...>::value;
};
协助 VC++ 消除歧义:
template<int I, typename T, typename U>
struct find_type< I, T, U >
{
static constexpr int value = std::is_same<T, U>::value ? I : -1;
};
当 ...Rest
为空时。
另一种可能的替代方法是通过模板函数,而不是 find_type
结构。
举个例子...如果你定义一个static constexpr
方法find_type_func()
如下(C++17,但如果你愿意,我可以很容易地将它改编成C++14)
template <typename T, typename ... List>
constexpr static int find_type_func ()
{
int ret { -1 };
int i { 0 };
((ret = (ret == -1) && std::is_same<T, List>{} ? i : ret, ++i), ...);
return ret;
}
你可以删除struct find_type
并初始化value
如下
static constexpr int value = find_type_func<Type, Types...>();
-- 编辑--
如所问,C++14版本
template <typename T, typename ... List>
constexpr static int find_type_func ()
{
using unused = int[];
int ret { -1 };
int i { 0 };
(void)unused { 0, (std::is_same<T, List>::value ? ret = i : ++i)... };
return ret;
}