0

我有一个特殊情况,我想测量关于我的 std::function 使用情况的统计信息。通常诸如花费时间、调用量、经常调用哪个函数以及有时用于测试之类的事情,例如随机抛出 nullptr 以检查我的代码如何处理它。

首先,我正在考虑从 std::func 继承,然后覆盖检索指针的函数 - 或类似的东西 - 但在阅读了几个主题和指南后,我得出结论,这是非常不明智的。

我的第二个想法是简单地创建一个包装类。重构我的整个代码以使用这个包装器而不是 std::function 并不难,所以没关系。我想避免的只是使用不必要和不舒服的用法,就像任何额外的功能一样。例如。:

std::function<...> dummyvar (...);

// Later I can call this dummy var as simply as dummyvar(...)
// I don't want to add extra complexity, like this:

CustomWrapper<...> customdummy (...);
customdummy.getVal()(...);

// Best would be if I could actually "simply" replace all std::function to the Custom Wrapper.

在我目前非常简单的情况下,不会复制 std::function,只需简单地初始化一次,必要时一直调用它。因此,如果它对您有所帮助,您可以考虑这一点并忽略其他东西,例如复制构造函数等(当然,自定义实现不缺少的功能越多越好,但我个人提到的已经足够了)


我不知道如何继续前进,这就是为什么我什至没有附上任何源代码。

4

3 回答 3

2

您可能会执行以下操作:

template <typename Sig>
class CustomWrapper
{
private:
    std::function<Sig> f;
    mutable std::size_t nbCall = 0;
    // ...
public:
    CustomWrapper() = default;

    CustomWrapper(const CustomWrapper&) = default;
    CustomWrapper(CustomWrapper&&) = default;
    CustomWrapper& operator=(const CustomWrapper&) = default;
    CustomWrapper& operator=(CustomWrapper&&) = default;

    template <typename T,
              std::enable_if_t<!std::is_same<CustomWrapper, std::decay_t<T>>::value
                  && std::is_constructible<std::function<Sig>, T&&>::value, bool> = false>
    CustomWrapper(T&& arg) : f(std::forward<T>(arg)){}

    template <typename ... Ts,
              std::enable_if_t<(sizeof...(Ts) >= 2)
                  && std::is_constructible<std::function<Sig>, Ts&&...>::value, bool> = false>
    CustomWrapper(Ts&& ... args) : f(std::forward<Ts>(args)...){}

    template <typename ... Ts>
    auto operator ()(Ts&&... args) const -> decltype(f(std::forward<Ts>(args)...))
    {
        ++nbCall; // Statistics you want
        // ...
        return f(std::forward<Ts>(args)...);
    }

    std::size_t getNbCall() const { return nbCall; }
    // ...
};

演示

于 2019-04-18T08:57:39.970 回答
1

我认为这是您可以用来创建包装器的想法:

template <typename T>
class CustomWrapper;

template <typename Result, typename ...Args>
class CustomWrapper<Result(Args...)>
{
public:
    template <typename ...SomeArgs>
    CustomWrapper(SomeArgs&&... args)
     : func(std::forward<SomeArgs>(args)...) 
    {
    }

    CustomWrapper(const CustomWrapper&) = default;
    CustomWrapper(CustomWrapper&&) = default;

    auto operator()(Args&&... args)
    {
        return func(std::forward<Args>(args)...);
    }

private:
    std::function<Result(Args...)> func;
};

void foo()
{
    CustomWrapper<void(int, int)> func([](int x1, int x2) {});
    func(1, 2);
}

我没有实现所有方法,但是很容易将它们添加为示例。

但我还想提一下,如果你std::function经常调用 s - 最好的办法是摆脱std::function它自己以提高性能。如果可能,请考虑切换到功能对象。

于 2019-04-18T08:46:35.563 回答
0

您是否希望在您的程序发货前不断检查统计信息还是只检查一次?如果只有一次我会建议使用分析器/覆盖工具来查看函数被引用了多少次。

如果您需要恒定的统计数据,您需要查看 std::function 接口(https://en.cppreference.com/w/cpp/utility/functional/function)并为此创建新的实现 - 这并不难实施。

于 2019-04-18T08:42:23.357 回答