【问题标题】:How to iterate over the size of a parameter pack with a compile-time index parameter如何使用编译时索引参数迭代参数包的大小
【发布时间】:2021-12-28 12:01:06
【问题描述】:

我正在尝试编写一个可变参数模板函数,其中包含一个循环,该循环遍历参数包中的每种类型。我正在使用它来构建一个元组,然后我在确定模板类型的回调函数上apply

我想我可以使用sizeof...(Args) 来做到这一点,如下所示:

template <typename ...Args>
void addCallback(void* handle, std::string address, std::function<void(Args...)> callback)
{

    return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
        std::tuple<Args...> args;
        for (size_t i = 0; i < sizeof...(Args); i++)
        {
            std::get<i>(args) = message.getArg<std::tuple_element_t<i, decltype(args)>(i);
        }

        std::apply(callback, std::move(args));
        });
}

这不会编译,因为std::get&lt;i&gt;(args) 要求i 是编译时间常数。但是,所有信息在编译时都可用。有没有办法使这项工作?我曾考虑过使用折叠表达式,但

我正在使用 C++17。

【问题讨论】:

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


    【解决方案1】:

    你可以定义一个辅助函数来使用index_sequence扩展Tuple的元素,并通过折叠表达式赋值。

    template<class Tuple, class Message, std::size_t... Is>
    void assign_tuple(Tuple& tuple, const Message& message, std::index_sequence<Is...>) {
      ((std::get<Is>(tuple) = message.getArg<std::tuple_element_t<Is, Tuple>(Is)), ...);
    };
    
    template <typename ...Args>
    auto addCallback(void* handle, std::string address, std::function<void(Args...)> callback) {
      return addMessageCallback(std::move(address), [callback](const ci::osc::Message& message) {
          std::tuple<Args...> args;
          assign_tuple(args, message, std::make_index_sequence<sizeof...(Args)>{});
          std::apply(callback, std::move(args));
      });
    }
    

    在 C++20 中,您只需在函数内定义模板 lambda 即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 2021-08-16
      • 2021-05-12
      相关资源
      最近更新 更多