C++ 模板参数推断失败,使用函数指针作为参数
我已经编写了许多模板函数。例如:C++ 模板参数推断失败,使用函数指针作为参数,c++,templates,visual-studio-2012,C++,Templates,Visual Studio 2012,我已经编写了许多模板函数。例如: template <typename T> inline int Foo(T* t, unsigned char** p, size_t* size, size_t (*MyHandler)(T*)) { ... } template <> inline int Foo<Bar>(Bar* t, unsigned char** p, size_t* size, size_t (*MyHandler)(Bar*)) {
template <typename T>
inline int Foo(T* t, unsigned char** p, size_t* size, size_t (*MyHandler)(T*))
{
...
}
template <>
inline int Foo<Bar>(Bar* t, unsigned char** p, size_t* size, size_t (*MyHandler)(Bar*))
{
...
}
然而,这一行导致了一对
- C2784:无法从“Bar*”推断“T*”的模板参数
- C2796:无法将函数模板'size\t FooFoo(t*)用作函数参数
Foo
一样,存在专门化Foo
据我所知,由于第一个参数的类型是T*
,所以应该可以对T进行推导,或者该函数指针与推导混淆了
如有任何提示,将不胜感激
更新3
根据@Yakk建议的变更请求提供MCV,最终有效
#include <stdio.h>
struct Bar
{
int a;
int b;
int c;
};
template<class T>struct id_t{typedef T type;};
template <typename T>
inline size_t FooFoo(T* t)
{
printf("FooFoo calculating size of T...\r\n", sizeof(T));
return sizeof(T);
}
template <>
inline size_t FooFoo<Bar>(Bar* t)
{
printf("FooFoo calculating size of Bar...\r\n", sizeof(Bar));
return sizeof(Bar);
}
template <typename T>
inline int Foo(T* t, unsigned char** p, size_t* size, typename id_t<size_t (*)(T*)>::type MyHandler)
{
printf("Foo telling size of T: %u\r\n", MyHandler(t));
return 0;
}
template <>
inline int Foo<Bar>(Bar* t, unsigned char** p, size_t* size, typename id_t<size_t (*)(Bar*)>::type MyHandler)
{
printf("Foo telling size of Bar: %u\r\n", MyHandler(t));
return 0;
}
int main(int argc, char* argv[])
{
int i;
Bar myBar;
Foo<Bar>(&myBar, nullptr, 0, FooFoo<Bar>); // works
Foo<int>(&i, nullptr, 0, FooFoo<int>); // works
Foo(&myBar, nullptr, 0, FooFoo<Bar>); // works
Foo(&i, nullptr, 0, FooFoo<int>); // works
Foo(&myBar, nullptr, 0, FooFoo); // error C2896: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : cannot use function template 'size_t FooFoo(T *)' as a function argument
// error C2784: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : could not deduce template argument for 'T *' from 'Bar *'
Foo(&i, nullptr, 0, FooFoo); // error C2896: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : cannot use function template 'size_t FooFoo(T *)' as a function argument
//error C2784: 'int Foo(T *,unsigned char **,size_t *,size_t (__cdecl *)(T *))' : could not deduce template argument for 'T *' from 'int *'
return 0;
}
#包括
结构条
{
INTA;
int b;
INTC;
};
templatestruct id_t{typedef t type;};
模板
内联尺寸(t*t)
{
printf(“FooFoo正在计算T的大小…。\r\n”,sizeof(T));
返回大小f(T);
}
模板
内联尺寸(Bar*t)
{
printf(“FooFoo正在计算棒材的尺寸…\r\n”,sizeof(棒材));
返回尺寸(巴);
}
模板
内联int Foo(T*T,无符号字符**p,size\u T*size,typename id\u T::type MyHandler)
{
printf(“Foo告诉T的大小:%u\r\n”,MyHandler(T));
返回0;
}
模板
内联int Foo(Bar*t,无符号字符**p,size\u t*size,typename id\u t::type MyHandler)
{
printf(“Foo告诉条的大小:%u\r\n”,MyHandler(t));
返回0;
}
int main(int argc,char*argv[])
{
int i;
我的酒吧;
Foo(&myBar,nullptr,0,FooFoo);//有效
Foo(&i,nullptr,0,FooFoo);//有效
Foo(&myBar,nullptr,0,FooFoo);//有效
Foo(&i,nullptr,0,FooFoo);//有效
Foo(&myBar,nullptr,0,FooFoo);//错误C2896:'int Foo(T*,unsigned char**,size_T*,size_T(__cdecl*)(T*)':无法将函数模板'size_T FooFoo(T*)用作函数参数
//错误C2784:“int Foo(T*,无符号字符**,size\u T*,size\u T(\u cdecl*)(T*)”:无法从“Bar*”推断“T*”的模板参数
Foo(&i,nullptr,0,FooFoo);//错误C2896:'int Foo(T*,无符号字符**,size_T*,size_T(__cdecl*)(T*))':无法将函数模板'size_T FooFoo(T*)用作函数参数
//错误C2784:“int Foo(T*,无符号字符**,size\u T*,size\u T(\u cdecl*)(T*)”:无法从“int*”推断“T*”的模板参数
返回0;
}
非常感谢 您的问题不是对
Foo
的T=Bar
的推导-而是对foooo
的推导所有参数在推导时权重相等,并且是独立推导的。要阻止使用特定参数进行推断,请执行以下操作:
template<class T>struct id_t{typedef T type;};
template<class T>using block_deduction=typename id_t<T>::type;
或者在非C++11编译器中:
typename id_t<size_t (*)(T*)>::type MyHandler
typename id\u t::type MyHandler
这样做的目的是将
MyHandler
参数的类型放入非推断上下文中。因此,编译器不会尝试,而是使用第一个参数的推导来确定T
。然后生成MyHandler
的类型。然后根据签名解析您传递的重载集,一切都正常(可能)。只是好奇,但您是否尝试过Foo(&myBar,pBuffer,size,FooFoo)代码>?无法使用g++5.1(TDM)、clang或VC2015复制-请在帖子中添加有关编译器的详细信息,这样我们就不必猜测错误所在。@Holt我已经更新了详细信息,编译器是MSVC2012@antipattern感谢您的更新,您的MCVE中有一个小错误(我想第一次返回应该是sizeof(T)
notT
.我没有MSVC2012,但我确认你给出的示例使用MSVC2015编译并运行良好,不知道它是否符合标准思想…@Holt感谢你的测试,这是一件好事,因为我这里只有这个旧版本,没有其他内容。我担心这毕竟是不可能的。好吧,我也有这种怀疑。另一方面,如果在第二个调用中我将Foo悬停,然后Intellisense确实显示了一个正确推导的签名:Foo(Bar*t,unsigned char pBuffer,size\t size,size\t(*MyHandler)(Bar*))
。感谢您添加解释。我是否也必须在专用Foo的情况下使用block_推断,还是仅在声明通用模板Foo时使用block_推断?因为Intellisense在专用Foo的声明中使用它时显示错误(“没有函数声明的实例与指定类型匹配”)。显然,我的Visual Studio版本不支持此功能。太糟糕了:/有没有办法使用
关键字摆脱?@antipattern使用typename id\u t::type MyHandler
,而不是Yakk在最后提出的方法。@Holt在第一行中已经出现错误:错误C2873:“type”:符号无法使用n使用声明。我在这里发现了一个模糊不清的类似问题,但无法使其对我起作用。@反模式您需要使用
声明完全删除,并使用我建议的内容,而不是阻止MyHandler
。
template<class T>struct id_t{typedef T type;};
template<class T>using block_deduction=typename id_t<T>::type;
block_deduction<size_t (*)(T*)> MyHandler
typename id_t<size_t (*)(T*)>::type MyHandler