Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板参数推断失败,使用函数指针作为参数_C++_Templates_Visual Studio 2012 - Fatal编程技术网

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)
not
T
.我没有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