比较不同长度的成员参数包

问题描述

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,type<2,1>>::value == false 编译。
  • are_compatibles<type<1,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 的回答启发,这里有一个更简单的版本来延迟可能不正确的包扩展的实例化:

ModTime

使用 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; }; 留给读者作为练习,因为它取决于特定的用例。

这可以用于任何使用 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) && ...)>
{};

Demo