整数参数特殊值的模板特化
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;
};
错误说明了一切:
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...>>;
};
我正在努力处理整数参数的模板特化,也许这根本不可能?
我尝试了什么:
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;
};
错误说明了一切:
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...>>;
};