比较不同长度的memberwise参数包
Compare memberwise parameter packs of different lengths
template <int... ValuesOrSentinals>
struct type {};
template <typename T, typename U>
struct are_compatibles;
template <int... TVals, int... UVals>
struct are_compatibles<type<TVals...>, type<UVals...>>
: public conjunction<bool_constant<sizeof...(TVals) == sizeof...(UVals)>,
bool_constant<((TVals == UVals) && ...)>> {};
这里我定义了两个参数包之间的兼容性检查。实际的成员检查比相等性检查更复杂,所以我不能回退到 is_same<integer_sequence<int, TVals...>, integer_sequence<int, UVals...>>
。我必须自己检查每个成员。
are_compatibles<type<1, 2>, type<1, 2>>::value == true;
编译。
are_compatibles<type<1, 2>, type<2, 1>>::value == false
编译。
are_compatibles<type<1, 2>, type<1>>::value == false
编译失败,因为参数包长度不一样
有没有办法比较不同长度的成员参数包?
分两个阶段进行。首先检查相同的长度,然后第二个(如果第一次通过,你只 运行)成对比较。
template<class...>struct always_false:std::false_type{};
template<template<class...>class Z>struct ztemplate{template<class...Ts>using apply=Z<Ts...>;};
template<class A, class B>
struct foo;
template<int...As, int...Bs>
struct foo<type<As...>,type<Bs...>>:
std::conditional<
sizeof...(As)==sizeof...(Bs),
ztemplate<are_compatible>,
ztemplate<always_false>
>::type::template apply<type<As...>,type<Bs...>>
{};
或类似的
受 Yakk 回答的启发,这里有一个更简单的版本来延迟可能不正确的包扩展的实例化:
template <bool Test, template <typename...> typename TrueType,
template <typename...> typename FalseType>
struct late_binding_conditional {
template <typename... Ts>
using instantiate = typename TrueType<Ts...>::type;
};
template <template <typename...> typename TrueType,
template <typename...> typename FalseType>
struct late_binding_conditional<false, TrueType, FalseType> {
template <typename... Ts>
using instantiate = typename FalseType<Ts...>::type;
};
使用 late_binding_conditional
留作 reader 的练习,因为它取决于具体用例。
这可以用于任何使用 type_trait 可能导致模板实例化无效的情况。因此它不限于包扩展。
另一种方式,使用启动器:
template <int... ValuesOrSentinals>
struct type {};
template <typename T, typename U, typename Enabler = void>
struct are_compatibles : std::false_type{};
template <int... TVals, int... UVals>
struct are_compatibles<type<TVals...>, type<UVals...>,
std::enable_if_t<sizeof...(TVals) == sizeof...(UVals)>>
: std::bool_constant<((TVals == UVals) && ...)>
{};
template <int... ValuesOrSentinals>
struct type {};
template <typename T, typename U>
struct are_compatibles;
template <int... TVals, int... UVals>
struct are_compatibles<type<TVals...>, type<UVals...>>
: public conjunction<bool_constant<sizeof...(TVals) == sizeof...(UVals)>,
bool_constant<((TVals == UVals) && ...)>> {};
这里我定义了两个参数包之间的兼容性检查。实际的成员检查比相等性检查更复杂,所以我不能回退到 is_same<integer_sequence<int, TVals...>, integer_sequence<int, UVals...>>
。我必须自己检查每个成员。
are_compatibles<type<1, 2>, type<1, 2>>::value == true;
编译。are_compatibles<type<1, 2>, type<2, 1>>::value == false
编译。are_compatibles<type<1, 2>, type<1>>::value == false
编译失败,因为参数包长度不一样
有没有办法比较不同长度的成员参数包?
分两个阶段进行。首先检查相同的长度,然后第二个(如果第一次通过,你只 运行)成对比较。
template<class...>struct always_false:std::false_type{};
template<template<class...>class Z>struct ztemplate{template<class...Ts>using apply=Z<Ts...>;};
template<class A, class B>
struct foo;
template<int...As, int...Bs>
struct foo<type<As...>,type<Bs...>>:
std::conditional<
sizeof...(As)==sizeof...(Bs),
ztemplate<are_compatible>,
ztemplate<always_false>
>::type::template apply<type<As...>,type<Bs...>>
{};
或类似的
受 Yakk 回答的启发,这里有一个更简单的版本来延迟可能不正确的包扩展的实例化:
template <bool Test, template <typename...> typename TrueType,
template <typename...> typename FalseType>
struct late_binding_conditional {
template <typename... Ts>
using instantiate = typename TrueType<Ts...>::type;
};
template <template <typename...> typename TrueType,
template <typename...> typename FalseType>
struct late_binding_conditional<false, TrueType, FalseType> {
template <typename... Ts>
using instantiate = typename FalseType<Ts...>::type;
};
使用 late_binding_conditional
留作 reader 的练习,因为它取决于具体用例。
这可以用于任何使用 type_trait 可能导致模板实例化无效的情况。因此它不限于包扩展。
另一种方式,使用启动器:
template <int... ValuesOrSentinals>
struct type {};
template <typename T, typename U, typename Enabler = void>
struct are_compatibles : std::false_type{};
template <int... TVals, int... UVals>
struct are_compatibles<type<TVals...>, type<UVals...>,
std::enable_if_t<sizeof...(TVals) == sizeof...(UVals)>>
: std::bool_constant<((TVals == UVals) && ...)>
{};