整数参数特殊值的模板特化

template specialization for special value of integer parameter

我正在努力处理整数参数的模板特化,也许这根本不可能?

我尝试了什么:

template< int COUNT, typename REMOVE, typename ...T>
struct RemoveFirstElementsImpl
{
    using Type= typename RemoveFirstElementsImpl<COUNT-1, T...>::Type;
};

template< typename ...T>
struct RemoveFirstElementsImpl<0, T...>
{
    using Type= TypeContainer<T...>;
};


template < int COUNT, typename ... T >
struct RemoveFirstElements
{
    using Type = typename RemoveFirstElementsImpl< COUNT, T...>::Type;
};

结果

error: partial specialization is not more specialized than the primary template because it replaces multiple parameters with a pack expansion

然后我想到了 SFINAE,比如:

template < int COUNT, typename = typename std::enable_if<COUNT==0>::type, typename HEAD, typename ... T >
struct RemoveFirstElements
{
    using Type= TypeContainer<T...>;
};
template < int COUNT, typename = void, typename HEAD, typename ... T >
struct RemoveFirstElements
{
    using Type= RemoveFirstElements<COUNT-1, T...>
};

但是我不知道如何将参数包和默认参数的组合获取到运行。

也许我走错了路。我想要实现的是获得一个参数列表,其中前 n 个参数从我的 TypeContainer 中删除,这只是一个扩展 std::tuple。我只需要类型本身而不需要任何参数,我只需要类型而不需要任何对象。

我想你想要:

template<int COUNT, typename ...Ts> struct RemoveFirstElementsImpl;

template<>
struct RemoveFirstElementsImpl<0>
{
    using type = std::tuple<>;
};

template<typename T, typename ...Ts>
struct RemoveFirstElementsImpl<0, T, Ts...>
{
    using type = std::tuple<T, Ts...>;
};

template<int N, typename T, typename ...Ts>
struct RemoveFirstElementsImpl<N, T, Ts...>
{
    using type = typename RemoveFirstElementsImpl<N - 1, Ts...>::type;
};

Live Demo

错误说明了一切:

partial specialization is not more specialized than the primary template because it replaces multiple parameters with a pack expansion

部分专业必须比主要专业更专业。在您的情况下,我们有一个更专业的元素(0 vs COUNT)和一个不太专业的元素 Ts... vs T, Ts...每个参数对。

所以我们可以为您的基本案例添加两个专业:

template <int, typename...> struct RemoveFirstElementsImpl;

// base case 1
template <>
struct RemoveFirstElementsImpl<0>
{
    using type = TypeContainer<>; // prefer lower-case type
};

// base case 2
template <typename T, typename... Ts>
struct RemoveFirstElementsImpl<0, T, Ts...>
{
    using type = TypeContainer<T, Ts...>;
};

// recursive case
template <int COUNT, typename T, typename... Ts>
struct RemoveFirstElementsImpl<COUNT, T, Ts...>
: RemoveFirstElementsImpl<COUNT-1, Ts...>
{ };

这行得通,但并不令人满意。让我们选择一种完全不同的方法。我们实际上可以在进行时弹出元素:

template <int COUNT, typename TC>
struct RemoveFirstElementsImpl
: RemoveFirstElementsImpl<COUNT-1, tail_t<TC>>
{ };

template <typename TC>
struct RemoveFirstElementsImpl<0, TC>
{
    using type = TC;
};

或者我们可以用 index_sequence:

作为一次迭代来完成
template <int COUNT, typename... Ts>
struct RemoveFirstElementsImpl
: RemoveFirstElementsImpl2<COUNT, TypeContainer<Ts...>,
                           std::make_index_sequence<sizeof...(Ts) - COUNT>
{ };

与:

template <int COUNT, typename TC, typename Seq>
struct RemoveFirstElementsImpl2;

template <int COUNT, typename TC, size_t... Is>
struct RemoveFirstElementsImpl2<COUNT, TC, std::index_sequence<Is...>>
{
    using type = TypeContainer<get_nth_t<Is+COUNT, TC>...>;
};

其中 get_nth_t<N, TC> 是要实现的元函数,returns 是给定 TypeContainer 中的第 N 类型。示例实现可能是:

template <int N, typename TC>
struct get_nth;

template <int N, typename TC>
using get_nth_t = typename get_nth<N, TC>::type;

template <int N, typename... Ts>
struct get_nth<N, TypeContainer<Ts...>> {
    using type = std::tuple_element_t<N, std::tuple<Ts...>>;
};