You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++:解决测量返回void的函数执行时间时的编译错误

解决测量void返回类型函数执行时间的编译错误

你遇到的编译错误根源在于:当被测函数返回void时,代码中auto ret = func(std::forward<Parameters>(args)...);试图声明一个void类型的变量——而C++语法不允许定义void类型的变量,因此触发Variable has incomplete type 'void'错误。

以下是两种可行的解决方案:

方案1:使用C++17的if constexpr分支处理

通过编译期判断函数返回类型是否为void,分别执行适配逻辑:

#include <iostream>
#include <chrono>
#include <type_traits>

template<class Func, typename... Parameters>
auto getTime(Func const &func, Parameters &&... args) {
    auto begin = std::chrono::system_clock::now();
    
    // 编译期分支:仅保留符合返回类型的代码逻辑
    if constexpr (std::is_void_v<std::invoke_result_t<Func, Parameters...>>) {
        func(std::forward<Parameters>(args)...);
        auto end = std::chrono::system_clock::now();
        std::cout << "The execution took " << std::chrono::duration<float>(end - begin).count() << " seconds.\n";
        // 无需返回值,隐式返回void
    } else {
        auto ret = func(std::forward<Parameters>(args)...);
        auto end = std::chrono::system_clock::now();
        std::cout << "The execution took " << std::chrono::duration<float>(end - begin).count() << " seconds.\n";
        return ret;
    }
}

int a() { return 0; }
void b() {}

int main()
{
    getTime(a);
    getTime(b);
    return 0;
}

说明:

  • std::invoke_result_t<Func, Parameters...>用于获取func传入args后的返回类型;
  • if constexpr是编译期分支,只会生成符合当前场景的代码,避免无效的void变量声明;
  • 该方案要求编译器支持C++17或更高版本。

方案2:模板重载(兼容C11/C14)

利用SFINAE(替换失败不是错误)实现重载,分别处理void和非void返回类型的函数:

#include <iostream>
#include <chrono>
#include <type_traits>

// 处理非void返回类型的函数
template<class Func, typename... Parameters>
auto getTime(Func const &func, Parameters &&... args)
    -> std::enable_if_t<!std::is_void_v<std::invoke_result_t<Func, Parameters...>>, 
                        std::invoke_result_t<Func, Parameters...>> {
    auto begin = std::chrono::system_clock::now();
    auto ret = func(std::forward<Parameters>(args)...);
    auto end = std::chrono::system_clock::now();
    std::cout << "The execution took " << std::chrono::duration<float>(end - begin).count() << " seconds.\n";
    return ret;
}

// 处理void返回类型的函数
template<class Func, typename... Parameters>
auto getTime(Func const &func, Parameters &&... args)
    -> std::enable_if_t<std::is_void_v<std::invoke_result_t<Func, Parameters...>>> {
    auto begin = std::chrono::system_clock::now();
    func(std::forward<Parameters>(args)...);
    auto end = std::chrono::system_clock::now();
    std::cout << "The execution took " << std::chrono::duration<float>(end - begin).count() << " seconds.\n";
}

int a() { return 0; }
void b() {}

int main()
{
    getTime(a);
    getTime(b);
    return 0;
}

说明:

  • std::enable_if_t用于在编译期筛选匹配的重载版本;
  • C11中可使用std::result_of_t<Func(Parameters...)>替代std::invoke_result_t(注意std::result_of在C17中已被弃用);
  • 该方案兼容C++11及以上版本。

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:12:31