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