Skip to content

Function as template parameter example

stackoverflow c++11: Templated wrapper function

I try to create a general wrapper function which takes any function as argument and also their parameters. Just something like the std::thread constructor.

#include <iostream>

using namespace std;

template<typename FUNCTION, typename ... ARGS>
void wrapper(FUNCTION &&func, ARGS &&... args)
{
    cout << "WRAPPER: BEFORE" << endl;
    auto res = func(args...);
    cout << "WRAPPER: AFTER" << endl;
    //return res;
}

int dummy(int a, int b)
{
    cout << a << '+' << b << '=' << (a + b) << endl;
    return a + b;
}

int main(void)
{
    dummy(3, 4);
    wrapper(dummy, 3, 4);
}
// g++ --std=c++11 test.cpp

NOTE:

1、上述代码是无法实现perfect forwarding的,正如评论所言:

You should be passing like this: func(std::forward<Args>(args)...)CoffeeandCode

2、A 中提供了完善版本

The wrapper function itself works. It calls the given function object (std::function, functor or just a "normal" function) with the given arguments. But i also like to return its return value.

A

C++11: std::result_of + std::forward

Use std::result_of :

#include <iostream>

using namespace std;
template<typename F, typename ...Args>
typename std::result_of<F&& (Args&&...)>::type wrapper(F &&f, Args &&... args)
{
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

int dummy(int a, int b)
{
    cout << a << '+' << b << '=' << (a + b) << endl;
    return a + b;
}
int main(void)
{
    dummy(3, 4);
    std::cout << wrapper(dummy, 3, 4) << std::endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++11

NOTE:

1、输出如下:

3+4=7
3+4=7
7

C++14: std::result_of_t + std::forward

In C++14 you can use the result_of_t alias:

template <typename F, typename ...Args>
std::result_of_t<F &&(Args &&...)> wrapper(F && f, Args &&... args)
{
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

NOTE:

1、完整测试程序如下:

#include <iostream>

using namespace std;
template <typename F, typename ...Args>
std::result_of_t<F &&(Args &&...)> wrapper(F && f, Args &&... args)
{
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

int dummy(int a, int b)
{
  cout << a << '+' << b << '=' << (a + b) << endl;
  return a + b;
}
int main(void)
{
  dummy(3, 4);
  std::cout << wrapper(dummy, 3, 4) << std::endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++14

C++14: decltype(auto) + std::forward

Or you can use return type deduction:

template <typename F, typename ...Args>
decltype(auto) wrapper(F && f, Args &&... args)
{
    std::cout << "before\n";
    auto && res = std::forward<F>(f)(std::forward<Args>(args)...);
    std::cout << "after\n";
    return res;
}

In C++14 you can also forget about result_of and friends completely and use return type deduction :)

NOTE:

1、完成测试程序如下:

#include <iostream>

using namespace std;

template <typename F, typename ...Args>
decltype(auto) wrapper(F && f, Args &&... args)
{
    std::cout << "before\n";
    auto && res = std::forward<F>(f)(std::forward<Args>(args)...);
    std::cout << "after\n";
    return res;
}
int dummy(int a, int b)
{
  cout << a << '+' << b << '=' << (a + b) << endl;
  return a + b;
}
int main(void)
{
  dummy(3, 4);
  std::cout << wrapper(dummy, 3, 4) << std::endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++14

A

C++11: auto + decltype + trailing return type

You can use decltype with the C++11 auto trailing return type :

#include <iostream>

using namespace std;

template<typename FUNCTION, typename ... ARGS>
auto wrapper(FUNCTION &&func, ARGS &&... args) -> decltype(func(std::forward<ARGS>(args)...))
{
    cout << "WRAPPER: BEFORE" << endl;
    auto res = func(args...);
    cout << "WRAPPER: AFTER" << endl;
    return res;
}

int dummy(int a, int b)
{
    cout << a << '+' << b << '=' << (a + b) << endl;
    return a + b;
}

int main(void)
{
    dummy(3, 4);
    cout << "WRAPPERS RES IS: " << wrapper(dummy, 3, 4) << endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++11

Live demo


And in C++14, simply do :

template<typename FUNCTION, typename... ARGS>
decltype(auto) wrapper(FUNCTION&& func, ARGS&&... args)

NOTE:

1、完整测试程序如下:

#include <iostream>

using namespace std;

template<typename FUNCTION, typename ... ARGS>
decltype(auto) wrapper(FUNCTION &&func, ARGS &&... args)
{
  cout << "WRAPPER: BEFORE" << endl;
  auto res = func(args...);
  cout << "WRAPPER: AFTER" << endl;
  return res;
}

int dummy(int a, int b)
{
  cout << a << '+' << b << '=' << (a + b) << endl;
  return a + b;
}

int main(void)
{
  dummy(3, 4);
  cout << "WRAPPERS RES IS: " << wrapper(dummy, 3, 4) << endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++14

Live demo

stackoverflow how to write a C++ class member function wrapper?

#include <iostream>
#include <string>
using namespace std;
class A
{
public:
    void connect()
    {
    }
    void close()
    {
    }
    template<typename F, typename ... Args>
    auto wrapper(F &&f, Args &&... args) -> typename std::result_of<F(Args...)>::type
    {
        using return_type = typename std::result_of<F(Args...)>::type;
        connect();
        return_type ret = f(args...);
        close();
        return ret;
    }
    bool c(int a, string b)
    {
    }
    string c(string b)
    {
        return b;
    }
    bool r(int a, string b)
    {
    }
};
int main()
{
    A a;
    a.connect();
    a.c(1, "abc");
    a.close(); // equal to a.wrapper(a.c, 1, "abc"); but compling error, how to write it correctly?
    cout << "result of a is: " << a.wrapper(a.c, 1, "abc") ? "successful" : "fail" << endl;
    cout << "result of another a is: " << a.wrapper(a.c, "abc") << endl;
    cout << "result of r is:" << a.wrapper(a.r, 1, "abc") << endl;
}
// g++ test.cpp -pedantic -Wall -Wextra --std=c++11

A

There are two ways to solve this:

1、Use std::bind. As in std::bind(&A::c, a)

2、Use a lambda. As in [&a](int i, std::string const& s) { return a.c(i, s); }

原文中的实现,没有perfect forwarding,下面是结合stackoverflow c++11: Templated wrapper function 中的写法

std::result_of + std::forward + lambda

#include <iostream>
#include <string>
#include <functional>
#include <type_traits> // std::result_of
using namespace std;
class A
{
public:
    A()
    {

    }
    A(int i)
    {

    }
    void connect()
    {
    }
    void close()
    {
    }
    template<typename F, typename ... Args>
    auto wrapper(F &&f, Args &&... args) -> typename std::result_of<F &&(Args&&...)>::type
    {
        using return_type = typename std::result_of<F &&(Args&&...)>::type;
        connect();
        return_type ret = std::forward < F > (f)(std::forward<Args>(args)...);
        close();
        return ret;
    }
    bool c(int a, string b)
    {
        return true;
    }
    string c(string b)
    {
        return b;
    }
    bool r(int a, string b)
    {
        return true;
    }
};
int main()
{
    A a;
    a.connect();
    a.c(1, "abc");
    a.close(); // equal to a.wrapper(a.c, 1, "abc"); but compling error, how to write it correctly?

    auto clbk = [&](int p1, string p2) -> bool {    return a.c(p1, p2);};
    bool ret = a.wrapper(clbk, 1, "abc");
    std::cout << a.wrapper(clbk, 1, "abc");
}
// g++ --std=c++11 test.cpp 

std::result_of + std::forward + std::bind

#include <iostream>
#include <string>
#include <type_traits> // std::result_of
#include <functional>
using namespace std::placeholders;
// for _1, _2, _3...
using namespace std;
using namespace std;
class A
{
public:
    A()
    {

    }
    A(int i)
    {

    }
    void connect()
    {
    }
    void close()
    {
    }
    template<typename F, typename ... Args>
    auto wrapper(F &&f, Args &&... args) -> typename std::result_of<F &&(Args&&...)>::type
    {
        using return_type = typename std::result_of<F &&(Args&&...)>::type;
        connect();
        return_type ret = std::forward < F > (f)(std::forward<Args>(args)...);
        close();
        return ret;
    }
    bool c(int a, string b)
    {
        return true;
    }
    string c(string b)
    {
        return b;
    }
    bool r(int a, string b)
    {
        return true;
    }
};
int main()
{
    A a;
    a.connect();
    a.c(1, "abc");
    a.close(); // equal to a.wrapper(a.c, 1, "abc"); but compling error, how to write it correctly?

    std::cout << a.wrapper(std::bind(&A::c, a), 1, "abc");
}
// g++ --std=c++11 test.cpp 

编译报错如下:

test.cpp: 在函数‘int main()’中:
test.cpp:55:43: 错误:对‘bind(<未解决的重载函数类型>, A&)’的调用没有匹配的函数
  std::cout << a.wrapper(std::bind(&A::c, a), 1, "abc");
                                           ^
test.cpp:55:43: 附注:备选是:
In file included from test.cpp:4:0:
/usr/include/c++/4.8.2/functional:1655:5: 附注:template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__or_<std::is_integral<typename std::decay<_Tp>::type>, std::is_enum<typename std::decay<_Tp>::type> >::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...)
     bind(_Func&& __f, _BoundArgs&&... __args)
     ^
/usr/include/c++/4.8.2/functional:1655:5: 附注:  template argument deduction/substitution failed:
test.cpp:55:43: 附注:  couldn't deduce template parameter _Func
  std::cout << a.wrapper(std::bind(&A::c, a), 1, "abc");
                                           ^
In file included from test.cpp:4:0:
/usr/include/c++/4.8.2/functional:1682:5: 附注:template<class _Result, class _Func, class ... _BoundArgs> typename std::_Bindres_helper<_Result, _Func, _BoundArgs>::type std::bind(_Func&&, _BoundArgs&& ...)
     bind(_Func&& __f, _BoundArgs&&... __args)
     ^
/usr/include/c++/4.8.2/functional:1682:5: 附注:  template argument deduction/substitution failed:
test.cpp:55:43: 附注:  couldn't deduce template parameter _Result
  std::cout << a.wrapper(std::bind(&A::c, a), 1, "abc");

按照回答中的写法:

#include <iostream>
#include <string>
#include <type_traits> // std::result_of
#include <functional>
using namespace std::placeholders;
// for _1, _2, _3...
using namespace std;
using namespace std;
class A
{
public:
    A()
    {

    }
    A(int i)
    {

    }
    void connect()
    {
    }
    void close()
    {
    }
    template<typename F, typename ... Args>
    auto wrapper(F &&f, Args &&... args) -> typename std::result_of<F &&(Args&&...)>::type
    {
        using return_type = typename std::result_of<F &&(Args&&...)>::type;
        connect();
        return_type ret = std::forward < F > (f)(std::forward<Args>(args)...);
        close();
        return ret;
    }
    bool c(int a, string b)
    {
        return true;
    }
    string c(string b)
    {
        return b;
    }
    bool r(int a, string b)
    {
        return true;
    }
};
int main()
{
    A a;
    a.connect();
    a.c(1, "abc");
    a.close(); // equal to a.wrapper(a.c, 1, "abc"); but compling error, how to write it correctly?

    using sig1 = bool(A::*)(int, string);
    cout << "result of a is: " << (a.wrapper(bind(static_cast<sig1>(&A::c), a, _1, _2), 1, string("abc")) ? "successful" : "fail") << endl;
}
// g++ --std=c++11 test.cpp