2016-07-29 14 views
1

Ich versuche, Code zu schreiben, etwas ähnliches (Code zu Demonstrationszwecken geschrieben) auf, dies zu tun:Wrapping einen Templat-Funktionsaufruf in einem Lambda-

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

I Also im Grunde ist versucht, eine Funktion zu schreiben, die eine zurückgibt Objekt, das Lambda übernimmt, das mit dem Funktionstyp "Templated" übereinstimmt. Offensichtlich funktioniert dieser Code nicht, weil ich keine Args ... definiert habe. Wie würde ich das in C++ 11 lösen?

+4

Können Sie mehr Kontext über das, was Sie versuchen, bieten? – templatetypedef

+0

Das '-> foo' nach' runFunc (F func) 'macht keinen Sinn. Probiere 'declltype (foo ([func] (Args ... args)' ... '))' – Czipperz

+0

Was ist 'foo()'? Versuchst du nur, 'Func' zu dekorieren? – Barry

Antwort

0

Noch ist nicht sicher, es ist das, was Sie suchen, ich riskiere Posting:

#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

Beachten Sie, dass Ihre Lösung C++ 14 erfordert. Sie können kein Lambda von einer Funktion in C++ 11 zurückgeben, Sie müssen es in einen benannten Typ umbrechen (zB: 'std :: function', Funktionszeiger ...). – KABoissonneault

+0

Oh, ich habe gerade festgestellt, dass das Lambda nicht das Objekt ist, das von der Funktion zurückgegeben wird. Nun, mein erster Punkt steht immer noch – KABoissonneault

+0

@KABoissonneault: welcher Teil erfordert * mehr * als OP-Code? – 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)}; 
} 

Dann:

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 */ } 
    }; 
} 

der Mangel an auto Parameter in C++ 11 Lambdas macht das über das Beste, was Sie tun können.

In C++ 14 ist dies trivial:

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

zustellen, dass viele nominell C++ 11 Compiler unterstützen tatsächlich auto Parameter auf Lambdas.

0

Sie eine Trägerstruktur, wie im folgenden Beispiel verwenden können:

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

Denn es mir nicht klar ist, was der Kontext des Problems ist, bin ich, dass ich nicht genau, bekam, was sie fragten.
Ich hoffe, der obige Code kann Ihnen helfen.