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
相关产品推荐
相关产品推荐

