【问题标题】:Create function parameter pack from Iterator pair从迭代器对创建函数参数包
【发布时间】:2015-02-15 06:23:35
【问题描述】:

我不知道如何使用从迭代器中检索到的可变数量的参数来调用函数。我有一个使用std::plus 的简单示例来说明问题:

#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/apply.hpp>
#include <iostream>
#include <array>

namespace mpl = boost::mpl;

int main() {
    using OP = std::plus<mpl::_>;
    std::array<int, 2> args = {1, 2};

    // This works (passing each arg separately)
    auto n1 = mpl::apply<OP, int>::type()(args[0], args[1]);

    std::cout << "plus (1,2) = " << n1 << std::endl;

    // what I want is more like:
    // auto n2 = mpl::apply<OP, int>::type()(args);
    // or
    // auto n3 = mpl::apply<OP, int>::type()(args.begin(), args.end());
}

我不知道如何跨越这个编译时/运行时界限。感谢您的任何指点!

【问题讨论】:

  • 首先,大小必须是编译时间常数;然后使用make_index_sequence 得到一个索引包,最后做一个包扩展得到一个元素列表。
  • 喜欢herehere?
  • @piotr:您的解决方案正是我想要的。我已将其复制到答案部分。随意复制我的答案,我会接受!

标签: c++ c++11 boost-mpl


【解决方案1】:

@PiotrS 在问题 cmets 部分的评论是正确答案。我在下面复制了他的答案(并针对 C++14 进行了更新——它清理了很多)。上面的@PiotrS 答案适用于 C++11(这是我所要求的)。

#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/apply.hpp>
#include <iostream> 
#include <array>
#include <utility>

namespace mpl = boost::mpl;

template <typename OP, typename T, typename Args, std::size_t... Is>
auto apply(Args&& args, std::index_sequence<Is...>)
{
    return typename mpl::apply<OP, T>::type()(std::get<Is>(std::forward<Args>(args))...);
}

template <typename OP, typename T, typename Args, std::size_t N = std::tuple_size<std::decay_t<Args>>{}>
auto apply(Args&& args)
{
    return apply<OP, T>(std::forward<Args>(args), std::make_index_sequence<N>{});
}

int main() {
    using OP = std::plus<mpl::_>;
    std::array<int, 2> args = {1, 2};

    auto n1 = mpl::apply<OP, int>::type()(args[0], args[1]);
    std::cout << "plus (1,2) = " << n1 << std::endl;

    auto n2 = apply<OP, int>(args);
    std::cout << "plus ([1,2]) = " << n2 << std::endl;
}

此解决方案利用参数的完美转发。调用语法正是我想要的。作为奖励,此解决方案适用于任何类似元组的参数类型(专门用于 std::get 和 std::tuple_size 的参数类型)。

感谢@PiotrS!

【讨论】:

    【解决方案2】:

    std::make_index_sequence 是一个出色的辅助元函数,用于此类目的:

    template <typename Func, typename T, size_t N, size_t... Inds>
    int ApplyFuncHelper(std::array<T, N> const& arr, std::index_sequence<Inds...>)
    {
     return Func()(arr[Inds]...);
    }
    
    template <typename Func, typename T, size_t N>
    int ApplyFunc(std::array<T, N> const& arr)
    {
     return ApplyFuncHelper<Func>(arr, std::make_index_sequence<N>());
    }
    

    Live Demo

    【讨论】:

    • std::get&lt;Inds, T, N&gt;(arr) -> TN 似乎是多余的。为什么你将返回类型硬编码为int
    • @PiotrS。是的。我从typename ArrayLike 之类的东西开始,然后尝试使用constexpr size()。在那里遇到了一个问题并采取了简单的方法:)让我在这里编辑它。谢谢!
    猜你喜欢
    • 2018-05-20
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多