问题描述
即对于以下 2 个类型列表(其中 Group
的工作方式类似于 std::variant):
class myclass;
using GroupA = Group<int,double,myclass>;
static_assert( GroupA::type_number<int> == 0 );
static_assert( GroupA::type_number<double> == 1 );
static_assert( GroupA::type_number<myclass> == 2 );
using GroupB = Group<double,myclass>; // different group => different numbering
static_assert( GroupB::type_number<double> == 0 );
static_assert( GroupB::type_number<myclass> == 1 );
我尝试通过 Types
进行递归,但我无法在每个 type
上得到一个模板参数
template < typename ... Types>
struct Group
{
template < typename T >
constexpr static int type_number = 0;
template < typename T,typename ... Types >
constexpr static int type_number = type_number<Types...> + 1;
};
我正在模仿 any
/variant
并且我希望能够对它们的向量进行排序。
解决方法
大致如下:
template <typename T,typename Head,typename ... Tail>
constexpr int TypeNumber(int start) {
if constexpr (std::is_same_v<T,Head>) {
return start;
} else {
return TypeNumber<T,Tail...>(start + 1);
}
}
template < typename ... Types>
struct Group
{
template < typename T >
constexpr static int type_number = TypeNumber<T,Types...>(0);
};
,
递归方式使代码编译时间更长。 诀窍是从一开始就使用配对,
然后,您可以使用重载按索引或按类型“选择”Text
(双标会导致模棱两可的调用)。
Pair
template <typename T,std::size_t I>
struct Pair
{
// possibly data,as `T data;` for tuple
};
template <typename T,std::size_t I>
constexpr std::integral_constant<std::size_t,I> type_number(Pair<T,I>) { return {}; }
template <typename Seq,typename ... Ts>
struct GroupImpl;
template <std::size_t ... Is,typename ... Ts>
struct GroupImpl<std::index_sequence<Is...>,Ts...> : Pair<Ts,Is>...
{
template <typename T>
constexpr static auto type_number() { return decltype(::type_number<T>(GroupImpl{})){}; }
};
template <typename ... Ts>
using Group = GroupImpl<std::make_index_sequence<sizeof...(Ts)>,Ts...>;
不是 C++11,但可以在 C++11 中实现
(在实例化数量上是线性的甚至是对数的)(在 C++14 中,在 std 中,编译器甚至可能使用内在的来只有一个实例化 :-) )