在lambda中包装模板化函数调用

时间:2016-07-29 16:00:27

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

我正在尝试编写代码来执行类似的操作(为演示目的而编写的代码):

template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
    return foo([func](Args... args) -> std::result_of<F>::type
        {
            // Do something before calling func
            func(args...);
            // Do something after call func
        });
}

所以基本上我正在尝试编写一个返回一个对象的函数,该对象采用与模板化函数类型匹配的lambda。显然这段代码不起作用,因为我没有定义Args。我如何在C ++ 11中解决这个问题?

3 个答案:

答案 0 :(得分:1)

template<class F_before, class F, class F_after>
struct decorate_func_t {
  F_before f0;
  F f1;
  F_after f2;

  template<class...Args>
  typename std::result_of<F(Args...)>::type operator()(Args&&...args)const{
    f0();
    auto r = f1(std::forward<Args>(args)...);
    f2();
    return r;
  }
};
template<class F_before, class F, class F_after>
decorate_func_t<F_before, F, F_after>
decorate_func( F_before before, F f, F_after after ){
  return {std::move(before), std::move(f), std::move(after)};
}

然后:

template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
  return foo(decorate_func(
        []{/* Do something before calling func */},
        func,
        []{/* Do something after call func */ }
  };
}

C ++ 11 lambdas中缺少auto参数使得这是你能做的最好的事情。

在C ++ 14中,这是微不足道的:

template <class F>
auto runFunc(F func)
{
  return foo(
    [func](auto&&... args) // ->decltype(auto) maybe
    {
      // Do something before calling func
      auto r = func(decltype(args)(args)...);
      // Do something after call func
      return r;
    }
  );
}

请注意,许多名义上的C ++ 11编译器实际上支持lambdas上的auto参数。

答案 1 :(得分:0)

仍然不确定这是你正在寻找的东西,我冒险张贴:

#include <iostream>

struct foo
{
    template<typename T>
    foo(T lambda)
    {
        lambda(1, 2);
    }
};

template <typename F, typename... Args>
inline typename std::result_of<F>::type runFunc(F func)
{
    return foo(
        [func](Args... args)
        {
            std::cout << "Before";
            func(args...);
            std::cout << "After";
        }
    );
}

struct print
{
    void operator()(int i) const
    {
        std::cout << i << std::endl;
    }

    void operator()(int i, int j) const
    {
        std::cout << i << " " << j << std::endl;
    }
};

int main()
{
    runFunc<print, int, int>(print());
}

答案 2 :(得分:0)

您可以使用支持结构,如以下示例所示:

#include<type_traits>
#include<cassert>

struct foo {
    template<typename F>
    foo(F f) { assert(42 == f(42)); }
};

template<typename>
struct S;

template<typename R, typename... Args>
struct S<R(*)(Args...)> {
    template <typename F>
    static auto runFunc(F func) -> foo
    {
        return foo{[func](Args... args) -> R
            {
                // Do something before calling func
                auto r = func(args...);
                // Do something after call func
                return r;
            }};
    }
};

template<typename F>
inline auto runFunc(F func) -> foo
{
    return S<F>::runFunc(func);
}

int f(int i) { return i; }

int main() {
    runFunc(f);
}

因为我不清楚问题的背景是什么,我不确定我到底要求的是什么。
我希望上面的代码可以帮到你。