在另一个std :: function中包装c ++ 11 std :: function?

moo*_*f2k 2 c++ boost boost-signals2 c++11

我想将一个std :: bind()或lambda的结果包装在一个帮助函数中,该函数跟踪函数调用的执行时间.我想要一个可以使用任意数量的参数(和类方法)的通用解决方案,并且兼容c ++ 11.

我的目的是获取包装函数并将其传递给boost :: signals2 :: signal,因此生成的函数对象需要与原始函数的签名相同.

我基本上正在寻找一些Wrapper像这样工作的神奇类或函数:

std::function<void(int)> f = [](int x) {
    std::cerr << x << std::endl;
};

boost::signals2::signal<void(int)> x_signal;
x_signal.connect(Wrapper<void(int)>(f));
x_signal(42);
Run Code Online (Sandbox Code Playgroud)

这将需要多长时间才能打印42.

谢谢!

seh*_*ehe 7

如果是关于性能的话,我强烈建议不要双重包装功能.

你可以没有那些:

template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
    return [f=std::forward<F>(f), task](auto&&... args) {
        using namespace std::chrono;

        struct measure {
            high_resolution_clock::time_point start;
            Caption const& task;
            ~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
        } timing { high_resolution_clock::now(), task };

        return f(std::forward<decltype(args)>(args)...);
    };
}
Run Code Online (Sandbox Code Playgroud)

观看现场演示:

Live On Coliru

#include <chrono>
#include <iostream>

template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
    return [f=std::forward<F>(f), task](auto&&... args) {
        using namespace std::chrono;

        struct measure {
            high_resolution_clock::time_point start;
            Caption const& task;
            ~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
        } timing { high_resolution_clock::now(), task };

        return f(std::forward<decltype(args)>(args)...);
    };
}

#include <thread>

int main() {
    using namespace std;
    auto f = timed("IO", [] { cout << "hello world\n"; return 42; });
    auto g = timed("Sleep", [](int i) { this_thread::sleep_for(chrono::seconds(i)); });

    g(1);
    f();
    g(2);

    std::function<int()> f_wrapped = f;
    return f_wrapped();
}
Run Code Online (Sandbox Code Playgroud)

打印(例如):

 -- (Sleep completed in 1000188µs)
hello world
 -- (IO completed in 2µs)
 -- (Sleep completed in 2000126µs)
hello world
 -- (IO completed in 1µs)
exitcode: 42
Run Code Online (Sandbox Code Playgroud)

更新:c ++ 11版本

Live On Coliru

#include <chrono>
#include <iostream>

namespace detail {

    template <typename F>
    struct timed_impl {
        std::string _caption;
        F _f;

        timed_impl(std::string const& task, F f) 
            : _caption(task), _f(std::move(f)) { }

        template <typename... Args>
        auto operator()(Args&&... args) const -> decltype(_f(std::forward<Args>(args)...))
        {
            using namespace std::chrono;

            struct measure {
                high_resolution_clock::time_point start;
                std::string const& task;
                ~measure() { std::cout << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
            } timing { high_resolution_clock::now(), _caption };

            return _f(std::forward<decltype(args)>(args)...);
        }
    };
}

template <typename F>
detail::timed_impl<F> timed(std::string const& task, F&& f) {
    return { task, std::forward<F>(f) };
}

#include <thread>

int main() {
    using namespace std;
    auto f = timed("IO", [] { cout << "hello world\n"; return 42; });
    auto g = timed("Sleep", [](int i) { this_thread::sleep_for(chrono::seconds(i)); });

    g(1);
    f();
    g(2);

    std::function<int()> f_wrapped = f;
    return f_wrapped();
}
Run Code Online (Sandbox Code Playgroud)