ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 如何编写连接两个函数的函数?

2019-08-23 19:06:41  阅读:208  来源: 互联网

标签:c lambda templates variadic-templates


我正在尝试编写一个泛型函数,它连接两个可以用同一组参数调用的函数,但是我遇到了一些麻烦.这是我到目前为止所拥有的. (不编译)

//A functor to store the input functions and call them
template <typename LEFT, typename RIGHT>
struct combine_functions {
  combine_functions(const LEFT &left, const RIGHT &right)
   : left(left), right(right) {}

  template <typename ...ARGS>
  std::enable_if_t<
    //My compiler doesn't have support for C++17 std library so I 
    //found an implementation of callable on SO
    is_callable_v<LEFT, std::decay_t<ARGS>...> &&
    is_callable_v<RIGHT, std::decay_t<ARGS>...>
  > operator()(ARGS... args) const {
    //the return value doesn't matter in my situation and can be 
    //completely discarded
    left(std::forward<ARGS>(args)...);
    right(std::forward<ARGS>(args)...);
  }

private:
  mutable LEFT left;
  mutable RIGHT right;
};

//I should probably have an enable if that checks the arguments 
//are function pointers or functors
template <typename LEFT, typename RIGHT>
combine_functions<
  std::decay_t<LEFT>,
  std::decay_t<RIGHT>
>
operator+(
  const LEFT &left,
  const RIGHT &right
) {
  return {left, right};
}

如果不清楚我想要实现什么,那么这里是一个测试.

#include <iostream>
#include "combine functions.hpp"    

struct A {
  void operator()(float &f, int i) {
    std::cout << "running A with float " << f << " and int " << i << '\n';
    f++;
  }
};

struct B {
  void operator()(float &f, int i) {
    std::cout << "running B with float " << f << " and int " << i << '\n';
    f++;
  }
};

struct C {
  void operator()(float &f, int i) {
    std::cout << "running C with float " << f << " and int " << i << '\n';
    f++;
  }
};

int main(int, const char**) {
  A a;
  B b;
  C c;
  auto abc = concat(concat(a, b), c);
  //or
  //auto abc = a + b + c;
  std::function<void(float &, int)> abcFunc = abc;
  float f = 5.0f;
  int i = 9;
  abcFunc(f, i);

  return EXIT_SUCCESS;
}

这是预期的产出

running A with float 5 and int 9
running B with float 6 and int 9
running C with float 7 and int 9    

>我如何在C中实现这一点?
>在这种情况下使用重载运算符是不明智的吗?
>“连接”是此操作的最佳术语吗?

预先感谢您的任何帮助.

解决方法:

我认为这是一个合理的起点.支持任意数量的连接和任意数量的具有完美转发的参数:

#include <tuple>
#include <utility>
#include <iostream>

namespace detail 
{
    template<class Tuple, std::size_t...Is, class...Args>
    void exec(Tuple&& tuple, std::index_sequence<Is...>, Args&&...args)
    {
        using expand = int[];
        void(expand{
            0,
            (std::get<Is>(tuple)(std::forward<Args>(args)...),0)...
        });

    }
}

template<class...Funcs>
auto concat(Funcs&&...funcs)
{
    constexpr auto nof_funcs = sizeof...(funcs);
    return [funcs = std::make_tuple(std::forward<Funcs>(funcs)...)](auto&&...args) mutable
    {
        detail::exec(funcs, 
                     std::make_index_sequence<nof_funcs>(), 
                     std::forward<decltype(args)>(args)...);
    };
};

int main()
{
    auto f1 = [](auto&& arg) { std::cout << arg << std::endl; };
    auto f2 = [](auto&& arg) { std::cerr << arg << std::endl; };

    concat(f1, f2)("Hello, World");
}

标签:c,lambda,templates,variadic-templates
来源: https://codeday.me/bug/20190823/1700321.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有