MSVC 2017 模板推导无法识别函数调用方式要如何绕过?

2018-05-02 13:15:11 +08:00
 after1990s

最近在研究 unique_ptr 的实现。其中需要分辨出函数类型和其他类型。 实验发现 MSVC 的编译器似乎无法正确的处理函数调用方式。

template <typename R>
struct is_unary_function_impl<R(__cdecl*)()>
{
    static const bool value = true;
};
template <typename R>
struct is_unary_function_impl<R(__cdecl*)(...)>
{
    static const bool value = true;
};


bool _cdecl unary_func_1() {
    return true;
}
bool _fastcall unary_func_2() {
    return true;
}

int main() 
{
ASSERT(true == is_unary_function<decltype(&unary_func_1)>::value);
//现在 value == false,它应该为 true。
ASSERT(true == is_unary_function<decltype(&unary_func_2)>::value); 
return 0;
}

如果在模板声明后面加上这样的代码:

template <typename R>
struct is_unary_function_impl<R(__stdcall*)()>
{
    static const bool value = true;
};
template <typename R>
struct is_unary_function_impl<R(__stdcall*)(...)>
{
    static const bool value = true;
};

编译器会给出一个编译错误

 error C2953: 'is_unary_function_impl<R(__cdecl *)(void)>': class template has already been defined

我要怎么改才能让编译器能识别_stdcall 的函数?

2143 次点击
所在节点    C
5 条回复
crazyneo
2018-05-02 14:43:35 +08:00
一、声明和实现要一致,以及,这种 decl 方式不能参与到模板特化的参数推演过程中去。
二、lambda 作为模板参数时应该用 std::function 外覆或->decltype 明确指出返回值,我翻了一下 14 之后的提案,并没有提及能不能在模板参数推演过程中正确的推导 lambda 表达式返回值类型。
gnaggnoyil
2018-05-02 17:50:39 +08:00
VS2017 表示没有 LZ 在字面上说的这些问题 https://godbolt.org/g/3CFDsT
MinGW64-GCC 表示情绪稳定 https://paste.ubuntu.com/p/WjfD7Yg2TP/
after1990s
2018-05-02 23:03:00 +08:00
@gnaggnoyil 因为 64 位编译器自动忽略了调用方式,64 位只有__fastcall。换成 32 位就报错了。
gnaggnoyil
2018-05-03 03:39:35 +08:00
@after1990s 刚注意到……你 stdcall 特化模板的类写错了,x86 msvc 下使用传参使用可变参数的函数不能是 stdcall 的,全都会被强制隐式声明成 cdecl,所以你要做的就是把最后一个特化模板给删掉. https://godbolt.org/g/5kZ8dH
after1990s
2018-05-03 08:51:39 +08:00
@gnaggnoyil 的确是这样,感谢! 改了一下可以匹配任意参数的_stdcall 了。https://godbolt.org/g/fChtgx

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/451423

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX