【问题标题】:Parameter pack expansion for variadic class member (tuple or other)可变类成员(元组或其他)的参数包扩展
【发布时间】:2021-08-13 16:04:01
【问题描述】:

我试图在一个类中存储一个引用元组(通过可变参数模板),然后我想“循环”它们并为它们赋值。

下面的函数process2 按预期工作,但我想让函数process1 工作相同(利用类本身的存储引用)。但是,我无法编译 process1。正确的方法是什么?有没有办法让成员 Args&... args; 而不是 std::tuple<Args&...> args (因为这可能允许参数扩展)?任何建议表示赞赏。

示例代码:

#include <tuple>
#include <string>
#include <iostream>

template<class... Args>
class Handler
{
private:
    template <class T>
    static bool process_arg(T& val)
    {
        if constexpr (std::is_same_v<T, int>)
            val = 123;
        else if constexpr (std::is_same_v<T, std::string>)
            val = "string";
        else
        {
            // do something
            return false;
        }
        return true;
    }

public:
    const std::tuple<Args&...> args;

    Handler(Args&... args)
        : args(args ...) { }

    // bool process1() const
    // {
    //     // Compile Error: operand of fold expression has no unexpanded parameter packs
    //     const bool success = (process_arg(args) && ...);

    //     // Compile Error: no matching function for process_arg(int&, int&, std::string&)
    //     bool success = true;
    //     std::apply([&success](auto &&... v) { success = success && process_arg(v...); }, args);
        
    //     return success;
    // }

    template<class... Args2>
    static bool process2(Args2&... args2)
    {
        const bool success = (process_arg(args2) && ...);
        return success;
    }
};

int main()
{
    int a, b;
    std::string c;

    // Handler(a, b, c).process1();
    Handler<>::process2(a, b, c);

    std::cout << a << "," << b << "," << c << "\n";

    return 0;
}

【问题讨论】:

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


    【解决方案1】:

    std::apply 正确,但语法不正确;包扩展需要在对process_arg 的调用之外。此外,您根本不需要变量success;您可以直接使用折叠表达式:

    bool process1() const
    {
      return std::apply([](auto &&... v) {
        return (process_arg(v) && ...); 
      }, args); 
    }
    

    这是demo

    【讨论】:

      【解决方案2】:

      不确定这是您需要的,因为它不会将任何内容存储为成员。但我认为它提供了所需的输出。哦,好吧...也许您可以从中汲取一些东西:)

      class Handler
      {
      private:
          template <class T>
          static bool process_arg(T& val)
          {
              if constexpr (std::is_same_v<T, int>)
                  val = 123;
              else if constexpr (std::is_same_v<T, std::string>)
                  val = "string";
              else
              {
                  // do something
                  return false;
              }
              return true;
          }
      
      public:
          template<typename arg_t, typename... args_t>
          static constexpr bool process(arg_t& arg, args_t&... args)
          {
              if constexpr (sizeof...(args_t) > 0)
              {
                  bool success = process_arg<arg_t>(arg) && process(args...);
                  return success;
              }
      
              return process_arg<arg_t>(arg);
          }
      };
      
      int main()
      {
          int a, b;
          std::string c;
          Handler::process(a, b, c);
          std::cout << a << "," << b << "," << c << "\n";
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-25
        • 2015-10-14
        • 1970-01-01
        • 2021-06-08
        • 2022-01-21
        • 2014-10-30
        相关资源
        最近更新 更多