2016-07-29 48 views
1

我想编写代码来做到这一点(用于演示目的编写的代码)类似的事情:结束语一个模板函数调用的拉姆达

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。很明显,这段代码不起作用,因为我没有定义的参数。我将如何在C++ 11中解决这个问题?

+4

你能提供更多关于你想要做什么的背景吗? – templatetypedef

+0

'runFunc(F func)'后的' - > foo'没有任何意义。试试'decltype(foo([func](Args ... args)'...'))' – Czipperz

+0

什么是'foo()'?你只是想装饰'func'? – Barry

回答

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()); 
} 
+0

请注意您的解决方案需要C++ 14。你不能从C++ 11中的函数返回一个lambda表达式,你需要用一个命名类型(例如:'std :: function',函数指针...)来包装它。 – KABoissonneault

+0

哦,我刚刚意识到lambda不是函数返回的对象。那么,我的第一点仍然是 – KABoissonneault

+0

@KABoissonneault:哪一部分比OP的代码要求*更多*? – lorro

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缺乏auto参数lambdas使得你可以做的最好。

在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编译器实际上支持lambda表达式auto参数。

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); 
} 

对于这我不清楚是什么问题的情况下,我不知道我有你问什么了。
我希望上面的代码可以帮助你。