【问题标题】:Match partially or completely type parameter pack部分或完全匹配类型参数包
【发布时间】:2018-07-03 13:59:15
【问题描述】:

我想检查类型参数包是否部分或完全与另一个参数包匹配。

到目前为止,我正在尝试这个:

template<typename... Arguments>
struct VariadicArguments
{
    template<typename... AnotherArguments>
    struct IsSame: std::bool_constant<sizeof...(AnotherArguments)==0> {};
};

template<typename Arg, typename... Arguments>
struct VariadicArguments<Arg, Arguments...>
{
    template<typename... Args>
    struct IsSame: std::false_type{};

    template<typename AnotherArg, typename... AnotherArguments>
    struct IsSame<AnotherArg, AnotherArguments...>:
        std::bool_constant<
            std::is_same<Arg, AnotherArg>::value &&
            VariadicArguments<Arguments...>::IsSame<AnotherArguments...>::value> { };

    template<>
    struct IsSame<> : std::true_type{};
};

template<>
struct VariadicArguments<>
{
    template<typename... Args>
    struct IsSame : std::false_type {};

    template<>
    struct IsSame<> : std::true_type {};
};

我猜到了

VariadicArguments<int, float, double>::IsSame<int, float>::value // true because (int, float, double) partially matches (int, float)
VariadicArguments<int, float, double>::IsSame<int, double>::value // false because (int, float, double) doesn't partially matches (int, double) it should be in serial
VariadicArguments<int, float, double>::IsSame<int, float, double>::value // true because they are all same in serial
VariadicArguments<int, float, double>::IsSame<>::value // true because no arguments matches every parameter pack.

但是我遇到了一些编译时错误

1>signal.hpp(25):错误 C2210: '_Val':打包扩展不能用作非打包的参数 别名模板中的参数

1>signal.hpp(25):注意:见 引用类模板实例化 'VariadicArguments::IsSame' 正在编译 1>d:\dell\source\repos\mimg\mimg-base\signal.hpp(29): 注意:参见类模板实例化的参考 'VariadicArguments' 正在编译

1>signal.hpp(25):错误 C3770: “未知类型”:不是有效的基类

1>signal.hpp(25):警告 C4346: 'VariadicArguments::IsSame':依赖名称不是 类型 1>d:\dell\source\repos\mimg\mimg-base\signal.hpp(25):注意: 带有'typename'的前缀表示类型

1>signal.hpp(25):错误 C2143: 语法错误:在 '::' 之前缺少 ','

1>signal.hpp(25):错误 C2039: “值”:不是“全局命名空间”的成员

1>signal.hpp(25):错误 C2143: 语法错误:在 '>' 之前缺少 ','

1>signal.hpp(41):错误 C3769: 'VariadicArguments':嵌套类不能与 立即封闭类

1>signal.hpp(57):错误 C2953: 'VariadicArguments::VariadicArguments': 类 模板已经定义

1>signal.hpp(16):注意:见 的声明 'VariadicArguments::VariadicArguments'

1>signal.hpp(67):错误 C3412: 'VariadicArguments': 不能在当前范围内专门化模板

【问题讨论】:

  • “部分或完全匹配”是什么意思?你能提供更准确的定义吗?
  • 我的意思是第一个参数包的类型与另一个参数包的类型相同。即, (type1, type2, type3) 匹配另一个参数包 (type4, type5, type6) 如果 is_same&lt;type1, type4&gt;::valueis_same&lt;type2, type5&gt;::valueis_same&lt;type3, type6&gt;::value
  • 但这……显然不是你的意思。你的意思是第二个包是第一个参数包的前缀吗?
  • 我的意思是它们匹配参数包中的每种类型

标签: c++ c++11 c++14 variadic-templates c++17


【解决方案1】:

我提出一个更简单的VariadicArguments(重命名为VarArgs以使其更短)

template <typename...>
struct VarArgs;

template <typename A0, typename ... As>
struct VarArgs<A0, As...>
 {
   template <typename ... Bs>
   struct IsSame  : std::integral_constant<bool, sizeof...(Bs)==0>
    { };

   template <typename ... Bs>
   struct IsSame<A0, Bs...> : VarArgs<As...>::template IsSame<Bs...>
    { };
 };

template <>
struct VarArgs<>
 {
   template <typename ... Bs>
   struct IsSame : std::integral_constant<bool, sizeof...(Bs)==0>
    { };
 };

现在你可以写了

int main ()
 {
   using ifd = VarArgs<int, float, double>;

   static_assert(  true == ifd::IsSame<int, float>::value, "1!" );
   static_assert( false == ifd::IsSame<int, double>::value, "2!" );
   static_assert(  true == ifd::IsSame<int, float, double>::value, "3!" );
   static_assert(  true == ifd::IsSame<>::value, "4!" );
 }

请注意,使用 std::integral_constant&lt;bool, BoolValue&gt; 而不是 std::bool_constant&lt;BoolValue&gt;,此解决方案也适用于 C++11 和 C++14,而不仅适用于 C++17。

【讨论】:

  • 谢谢!你能解释一下这行struct IsSame&lt;A0, Bs...&gt; : VarArgs&lt;As...&gt;::template IsSame&lt;Bs...&gt;为什么需要template来访问成员IsSame
  • @Mohit - 嗯......我从来没有完全理解过,确切地说,template 关键字是否必要;问题(据我所知)是在某些情况下,解析代码时,编译器不知道名称是否引用模板方法(因此以下&lt; 是显式模板参数列表的开始)与否(因此以下&lt; 可以是关系(小于)运算符)。因此,在您的情况下,template 是通知编译器 IsSame 是模板方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多