MSVC 2017中使用std::invoke_result处理auto返回值模板函数的问题
解决MSVC 2017中
std::invoke_result与返回值为auto的模板函数兼容问题 这确实是MSVC 2017的编译器Bug——按照C++17标准,你的代码完全合法,GCC、Clang、ICC等编译器都能正确处理,但MSVC 2017在推导返回值为auto的模板实例化函数类型时存在缺陷,错误地认为decltype(&add_auto_template_fn<int>)中包含未解析的auto类型,从而抛出编译错误。
问题复现代码
#include <type_traits> template<typename U> auto add_auto_template_fn(U a) { return a + 42; } void static_test_invoke_result() { using T = std::invoke_result< decltype(&add_auto_template_fn<int>), int>::type; static_assert(std::is_same<T, int>::value, ""); }
可行的解决方法
你已经找到的临时修复方案非常有效:通过定义一个函数指针变量,强制编译器提前推导模板实例化后的完整函数类型。
修改后的代码如下:
#include <type_traits> template<typename U> auto add_auto_template_fn(U a) { return a + 42; } void static_test_invoke_result() { auto f = add_auto_template_fn<int>; // 强制编译器推导函数的完整类型 using T = std::invoke_result< decltype(add_auto_template_fn<int>), int>::type; static_assert(std::is_same<T, int>::value, ""); }
这行auto f = add_auto_template_fn<int>;的作用是让MSVC提前解析add_auto_template_fn<int>的具体函数签名,后续再调用decltype(add_auto_template_fn<int>)时,编译器就能正确识别出它的完整类型(而非带有auto的不完整类型),从而绕过Bug避免报错。
如果你不想额外定义变量,也可以直接用decltype推导函数调用的返回值来替代std::invoke_result,写法如下:
using T = decltype(add_auto_template_fn<int>(std::declval<int>()));
这种方式绕开了std::invoke_result对函数类型的依赖,同样能在MSVC 2017中正常工作。
内容的提问来源于stack exchange,提问作者Pascal T.
相关产品推荐
相关产品推荐

