【问题标题】:c++ packing and unpacking parameter pack to call matching function pointer without stlc++打包解包参数包调用匹配函数指针不带stl
【发布时间】:2016-03-24 12:31:31
【问题描述】:

我正在尝试创建一个类,该类将存储指向具有可变数量参数的函数的指针,并稍后调用它。

这个想法是为函数创建一个包装器,该包装器将在对象破坏时调用所述函数。这样我就可以确保在退出某些功能后进行一些清理。

我现在拥有的是由 Faheem Mitha 编写的一些修改过的代码,发布在 here

这是带有示例的工作代码(我正在使用 Visual Studio 2015 编译它):

#include "stdafx.h"
#include <tuple>
#include <iostream>

using namespace std;

template<int...> struct seq {};

template<int N, int... S> struct gens : gens<N - 1, N - 1, S...> {};

template<int... S> struct gens<0, S...> { typedef seq<S...> type; };

template<typename Return, typename... Args> class CallOnExit
{
    Return(*_func)(Args...);
    std::tuple<Args...> _args;

    template<int... S> Return call_func(seq<S...>)
    {
        return _func(std::get<S>(_args)...);
    }
    Return call()
    {
        return call_func(typename gens<sizeof...(Args)>::type());
    }
public:
    CallOnExit(Return(*func)(Args...), Args&&... args)
    {
        _func = func;
        _args = std::forward_as_tuple(args...);
    }
    ~CallOnExit()
    {
        if (_func != nullptr)
            call();
    }
};

void f(int i, double d)
{
    cout << i << endl << d << endl;
}

int main()
{
    {
        CallOnExit<void, int, double> c(f, 1, 2);
    }
    cin.get();
    return 0;
}

问题是我必须在 stl 不可用的 Arduino 平台上进行这项工作(所以没有 std::tuple,没有 std::forward,没有 std::get)。 Arduino 支持 C++11。

在没有 stl 的情况下使这个示例工作所需的最少工作量是多少?

【问题讨论】:

  • 显而易见的答案:从某个地方复制缺失的部分?
  • 自己实现std::tuplestd::forwardstd::get
  • 是的,假设库中的操作系统内容没有依赖关系,这可以工作。但我想知道如何轻松实现一些最小的东西,就像元组和其他缺失的函数一样。

标签: c++ arduino variadic-templates


【解决方案1】:

这个想法是为函数创建一个包装器,该包装器将在对象破坏时调用所述函数。这样我就可以确保在退出某些功能后进行一些清理。

您尝试使用的代码似乎有些经过深思熟虑,或者至少是针对某些其他特定用途量身定制的。对于上面的引用,这是我如何使用 lambdas 和简单函数来完成任务。

现在可以根据需要自定义调用,并且实现保持简洁:

template< typename T > struct TRef{
  TRef(T &in) : t(in) {}
  ~TRef(){ t(); }
  T t;
};

template< typename T > TRef<T> RunOnExit(T t){
    return TRef<T>( t );
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  int a = 3, b = 4;
  auto test = RunOnExit( [](){ func(1, 2); } );
  {
    auto test1 = RunOnExit( [&a, &b](){ func(a, b); } );

  }
}

void func( int a, int b){
  auto pause = RunOnExit( wait );
  Serial.print( a, HEX );
  Serial.print( ", " );
  Serial.println( b, HEX );
}

void wait(){ delay(500); }

【讨论】:

    【解决方案2】:

    希望对你有帮助

    #include <tuple> 
    #include <iostream>
    
    using namespace std;
    
    template<int...> struct seq {};
    
    template<int N, int... S> struct gens : gens<N - 1, N - 1, S...> {};
    
    template<int... S> struct gens<0, S...> { typedef seq<S...> type; };
    
    // NEW
    template <int N, typename ... Args>
    struct typeCont;
    
    template <typename A0, typename ... Args>
    struct typeCont<0, A0, Args...>
     { using  type = A0; };
    
    template <int N, typename A0, typename ... Args>
    struct typeCont<N, A0, Args...>
     { using  type = typename typeCont<N-1, Args...>::type; };
    
    // NEW
    template <typename X, typename ... Args>
    class packCont;
    
    template <typename X, typename A0, typename ... Args>
    class packCont<X, A0, Args...>
     {
       public:
    
          X                      x;
          packCont<A0, Args...>  n;
    
       public:
    
          packCont (X const & x0, A0 const & a0, Args const & ... args)
            : x(x0), n(a0, args...)
             { }
    
          X const & getX () const
           { return x; }
    
          packCont<A0, Args...> const & getN () const
           { return n; }
     };
    
    
    
    template <typename X>
    class packCont<X>
     {
       private:
    
          X  x;
    
       public:
    
          packCont (X const & x0)
             : x(x0)
              { }
    
          X const & getX () const
           { return x; }
     };
    
    // NEW
    template <int N>
    struct getPc
     {
       template <typename ... Args>
          static typename typeCont<N, Args...>::type const &
          func (packCont<Args...> const & pc)
           { return getPc<N-1>::func(pc.getN()); }
     };
    
    template <>
    struct getPc<0>
     {
       template <typename A0, typename ... Args>
          static A0 const & func (packCont<A0, Args...> const & pc)
           { return pc.getX(); }
     };
    
    template<typename Return, typename... Args> class CallOnExit
     {
       Return(*_func)(Args...);
       packCont<Args...> _args; // MODIFIED
    
       // MODIFIED
       template<int... S> Return call_func(seq<S...>)
        {
          return _func( getPc<S>:: template func<Args...>(this->_args) ... );
        }
       Return call()
        {
          return call_func(typename gens<sizeof...(Args)>::type());
        }
       public:
       // MODIFIED
       CallOnExit(Return(*func)(Args...), Args&&... args)
          : _func(func), _args(args...)
        { }
       ~CallOnExit()
        {
          if (_func != nullptr)
             call();
        }
     };
    
    void f(int i, double d)
     {
       cout << i << endl << d << endl;
     }
    
    int main()
     {
        {
          CallOnExit<void, int, double> c(f, 1, 2);
        }
       cin.get();
       return 0;
     }
    

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 2013-12-01
      • 2021-12-09
      • 2021-12-10
      • 2021-09-29
      • 1970-01-01
      • 2022-08-13
      • 1970-01-01
      • 2019-04-14
      相关资源
      最近更新 更多