简体   繁体   English

具有可变参数模板的功能对象

[英]Function objects with variadic template

How can I define a function object that can be passed to apply? 如何定义可以传递以应用的功能对象? Ultimately, I want a function F f that can take all the elements of the tuple and push them back ta vector. 最终,我想要一个函数F f,该函数可以采用元组的所有元素并将其推回ta向量。

template <class F, size_t... Is>
constexpr auto index_apply_impl(F f, index_sequence<Is...>) {
    return f(integral_constant<size_t, Is> {}...);
}

template <size_t N, class F>
constexpr auto index_apply(F f) {
    return index_apply_impl(f, make_index_sequence<N>{});
}

template <class Tuple, class F>
constexpr auto apply(Tuple t, F f) {
    return index_apply<tuple_size<Tuple>{}>(
        [&](auto... Is) { return f(get<Is>(t)...); });
}

Thanks :) 谢谢 :)

You can use the expander trick . 您可以使用扩展器技巧 This needs C++14 though. 不过这需要C ++ 14。 I don't know what your byte array format looks like, so I just took a generic struct with a string member and convert everything to string in the constructor. 我不知道您的字节数组格式是什么样子,所以我只带了一个带有字符串成员的通用结构,然后在构造函数中将所有内容都转换为字符串。

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

template < typename T, typename F, size_t ... Is >
void for_each_impl(T&& t, F&& f, std::index_sequence<Is...>)
{
  using expand_type = int[];
  (void) expand_type { 0, ( (void) f(std::get<Is>(t)), 0) ... };
}

template < typename... Args, typename F >
void for_each(std::tuple<Args...> const& t, F&& f)
{
  for_each_impl(t, f, std::make_index_sequence<sizeof...(Args)>{});
}


struct Bytes {
  std::string str;
  Bytes(char const * c) : str(c) {};
  Bytes(int i) : str(std::to_string(i)) {};
  Bytes(char c) : str(1, c) {};
};


int main()
{
  auto t = std::make_tuple(12, "abc", 10, 'c', 1);
  std::vector<Bytes> v;
  for_each(t, [&v](auto&& x){ v.push_back(x); });

  for (auto const& e : v)
    std::cout << e.str << ' ';
  std::cout << '\n';
}

Live example 现场例子


In C++17 it is much easier, thanks to variadic lambda, fold expression , and std::apply . 在C ++ 17中,这要容易得多,这要归功于可变参数lambda, fold expressionstd::apply

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

struct Bytes {
  std::string str;
  Bytes(char const * c) : str(c) {};
  Bytes(int i) : str(std::to_string(i)) {};
  Bytes(char c) : str(1, c) {};
};


int main()
{
  auto t = std::make_tuple(12, "abc", 10, 'c', 1);
  std::vector<Bytes> v;
  std::apply([&v](auto&&... x){ (... , v.push_back(x)); }, t);

  for (auto const& e : v)
    std::cout << e.str << ' ';
  std::cout << '\n';
}

Live example 现场例子


If you cannot use C++11 your life will be painful. 如果您不能使用C ++ 11,您的生活将会很痛苦。 You have to roll your own implementation of index_sequence and you have to define a helper struct with templated call operator to substitute the generic lambda. 您必须滚动自己的index_sequence实现,并且必须使用模板化调用运算符定义一个辅助结构来替代通用lambda。

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

// https://stackoverflow.com/a/24481400/1944004
template <size_t ...I>
struct index_sequence {};

template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};

template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};


// Call a function for each element in a tuple

template < typename T, typename F, size_t ... Is >
void for_each_impl(T&& t, F&& f, index_sequence<Is...>)
{
  using expand_type = int[];
  (void) expand_type { 0, ( (void) f(std::get<Is>(t)), 0) ... };
}

template < typename... Args, typename F >
void for_each(std::tuple<Args...> const& t, F&& f)
{
  for_each_impl(t, f, make_index_sequence<sizeof...(Args)>{});
}

// "Byte array" emulation

struct Bytes {
  std::string str;
  Bytes(char const * c) : str(c) {};
  Bytes(int i) : str(std::to_string(i)) {};
  Bytes(char c) : str(1, c) {};
};

// Surrogate template lambda

struct Visitor
{
  std::vector<Bytes>& v;
  Visitor(std::vector<Bytes>& vb) : v(vb) {};
  template < typename T >
  void operator() (T&& x) { v.push_back(x); }
};


int main()
{
  auto t = std::make_tuple(12, "abc", 10, 'c', 1);
  std::vector<Bytes> v;
  for_each(t, Visitor(v));

  for (auto const& e : v)
    std::cout << e.str << ' ';
  std::cout << '\n';
}

Live example 现场例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM