其他分享
首页 > 其他分享> > c – 完美转发void和non-void返回函数

c – 完美转发void和non-void返回函数

作者:互联网

以前我用宏来测量函数调用的时间,每当我想快速检查时.现在,在C 11可用的情况下,我想最终删除预处理器代码的丑陋和平,并用以下内容替换它:

template <typename Functor, typename ... Args>
auto measure(Functor f, Args && ... args)
    -> decltype(f(std::forward<Args>(args)...))
{
    auto now = std::chrono::high_resolution_clock::now();
    auto ret = f(std::forward<Args>(args)...);
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::high_resolution_clock::now() - now).count();
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;

    return ret;
}

对于返回某些内容的函数(即非空),它可以正常工作.因此我觉得我需要为void函数重载 – 但是你不能仅仅在返回类型上重载函数.

我尝试使用一些模板魔法来解决这个问题,但无济于事;编译器仍然抱怨函数测量定义了两次:

template <
    typename Functor, typename ... Args,
    typename ReturnType = typename std::enable_if<
        !std::is_void<
            typename std::result_of<Functor(Args...)>::type
        >::value,
        typename std::result_of<Functor(Args...)>::type
    >::type
>
ReturnType measure(Functor f, Args && ... args)
{
    auto now = std::chrono::high_resolution_clock::now();
    auto ret = f(std::forward<Args>(args)...);
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::high_resolution_clock::now() - now).count();
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;

    return ret;
}

template <
    typename Functor, typename ... Args,
    typename ReturnType = typename std::enable_if<
        std::is_void<
            typename std::result_of<Functor(Args...)>::type
        >::value
    >::type
>
ReturnType measure(Functor f, Args && ... args)
{
    auto now = std::chrono::high_resolution_clock::now();
    f(std::forward<Args>(args)...);
    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
        std::chrono::high_resolution_clock::now() - now).count();
    std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
}

有没有解决的办法?

UPDATE

这是我现在使用的功能感谢R. Martinho Fernandes:

template <typename Functor, typename ... Args>
auto measure(Functor f, Args && ... args)
    -> decltype(f(std::forward<Args>(args)...))
{
    struct scoped_timer
    {
        scoped_timer() : now_(std::chrono::high_resolution_clock::now()) {}
        ~scoped_timer()
        {
            auto elapsed = std::chrono::duration_cast<
                    std::chrono::milliseconds
                >(std::chrono::high_resolution_clock::now() - now_).count();
            std::cout << "Time elapsed: " << elapsed << "ms" << std::endl;
        }

        private:
            std::chrono::high_resolution_clock::time_point const now_;
    } scoped_timer;

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

解决方法:

问题是默认模板参数不会生成不同的模板,就像默认函数参数不会对不同的重载一样.有一些方法,我在Remastered enable_if文章中描述了它们.

但是,我不会这样做.我只是利用这样一个事实:在通用代码中你可以“返回void”,并使用RAII打印出已用时间:

template <typename Functor, typename ... Args>
auto measure(Functor f, Args && ... args)
    -> decltype(f(std::forward<Args>(args)...))
{
    scoped_timer timer;
    return f(std::forward<Args>(args)...);
}

scoped_timer类可以简单地编写:现在在构造函数中保存,并在析构函数中计算和输出.

标签:c,c11,rvalue-reference,overloading
来源: https://codeday.me/bug/20190930/1835716.html