【问题标题】:fixed size container to variadic template argument list conversion固定大小的容器到可变参数模板参数列表的转换
【发布时间】:2016-04-22 19:44:33
【问题描述】:

我必须调用一个可变参数模板函数,它可以接受任意数量的参数。

template < class ... Args >
void f( Args&... args);

我希望编写一个小型包装函数,以便我可以调用 f,并使用包含在固定大小容器(如 std::array)中的 N 个相同类型的参数。

目标是写类似的东西

std::array<int, 3> arr = {1,2,3};
wrapper(arr); // calls f(1,2,3);

我尝试使用初始化列表和std::forward 的某种组合,但无济于事。有没有办法实现我想要的?

【问题讨论】:

  • 我想你可能正在寻找std::integer_sequence
  • 我看到了使其通用化的两个问题:从您的容器创建一个元组,并将元组解包到参数包中。后一部分have already been done 留下了元组的创建,不幸的是我不知道该怎么做。
  • @Louen 你可以使用make_tuple
  • 你需要有一个参数包。我认为您不能将数组转换为参数包。
  • @NathanOliver 就像将元组转换为参数包一样简单,因为std::array 具有相同的接口(@98​​7654330@、std::tuple_size 等)。

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


【解决方案1】:

如果您的编译器支持 C++14,您可以通过以下方式进行:

template <class ... Args>
void f(Args&&... args) {
...
}

template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, std::index_sequence<I...>) {
  f(arr[I]...);
}

template<typename T, std::size_t N, 
         typename Indices = std::make_index_sequence<N>>
void wrapper(std::array<T, N> const &arr) {
  wrapper_impl(arr, Indices());
}

Live Demo

对于基于此SO answer 的 C++11,您可以编写一些额外的机器并按如下方式执行(虽然尚未测试):

namespace detail {
  template<std::size_t... Is>        struct seq {};
  template<std::size_t N, int... Is> struct gen_seq : gen_seq<N-1,N-1, Is...> {};
  template<std::size_t... Is>        struct gen_seq<0, Is...> : seq<Is...> {};
}

template <class ... Args>
void f(Args&&... args) {
...
}

template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, detail::seq<I...>) {
  f(arr[I]...);
}

template<typename T, std::size_t N>
void wrapper(std::array<T, N> const &arr) {
  wrapper_impl(arr, detail::gen_seq<N>());
}

Live Demo

【讨论】:

    【解决方案2】:

    我设法使用 std::array 解决了这个问题,灵感来自 How do I expand a tuple into variadic template function's arguments? 中的元组解决方案

    (已编辑:std::array 版本,第一个版本使用原始指针)

    // Function I want to call : 
    template< class... Args >
    void f( Args&... args ) {
        // ...
    }
    

    使用从数组末尾获取参数的递归模板(以便它们以正确的顺序结束)。 I = 0 的特化具​​有 Args..args 中的所有参数并调用 f()

    namespace Helper {
    template< unsigned int N, unsigned int I > 
    struct Caller {
        template< class T, class...Args >
        static void call( const std::array<T,N>& arr, Args&... args  ){
            Caller<N,I-1>::call( arr, std::get<I-1>(arr), args... );
        }
    };
    
    template < unsigned int N >
    struct Caller<N, 0> {
        template< class T, class...Args >
        static void call( const std::array<T,N>&  arr, Args&... args ) {
            f(args...);
        }
    };
    }
    

    让我们用一个漂亮的函数把它包装起来

    template< typename T, unsigned N >
    void call_f( const std::array<T,N>& arr ){
        Helper::Caller<N,N>::call(arr);
    }
    

    这是调用代码的样子。

    std::array<float,3> array = {4.3, 3.14,2.1} ;
    call_f(array);
    

    Live version here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 2020-04-21
      • 1970-01-01
      相关资源
      最近更新 更多