我正在努力使用整数参数的模板特化,也许这根本不可能?
我尝试了什么:
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;
};
结果
错误:部分特化并不比主模板更专业化,因为它用包扩展替换了多个参数
然后我想到了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...>
};
但我不知道如何运行参数包和默认参数的组合。
也许我完全错了。我想要实现的是获取一个参数列表,其中从我的TypeContainer中删除前n个参数,这只是一个扩展的std :: tuple。我只需要类型本身而不是任何参数,我只需要在类型而不是任何对象上。
答案 0 :(得分:3)
我想你想要:
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;
};
答案 1 :(得分:2)
错误说明了一切:
部分特化并不比主模板更专业化,因为它用包扩展替换了多个参数
部分专业化必须比主要专业化更专业化。在您的情况下,我们有一个更专业的元素(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>
是要实现的元函数,返回给定N
中的TypeContainer
类型。示例实现可能是:
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...>>;
};