让函数指针模板参数接受右值引用是不是合法?

Posted

技术标签:

【中文标题】让函数指针模板参数接受右值引用是不是合法?【英文标题】:Is it legal to have a function pointer template parameter accept an rvalue reference?让函数指针模板参数接受右值引用是否合法? 【发布时间】:2014-10-29 13:39:14 【问题描述】:

使用 Microsoft Visual Studio 2012,我尝试编译以下内容:

template <void (*f)(int && y)>
void foo() 

并得到这个错误:

error C2993: 'int &&' : illegal type for non-type template parameter 'y'

这真的违法吗?或者这是 MSVS 中的错误?如果是这样,有谁知道它是否适用于更高版本?

【问题讨论】:

这里没有违法的。可能是 MSVC 被函数指针类型的第一个参数的名称 y 混淆了,这里没有必要。试试template &lt;void (*f)(int&amp;&amp;)&gt; 对于 G++,您必须添加 -std=c++0x 作为编译器选项,否则它将无法解析。 jrok,你太棒了!删除“y”可以解决该错误。如果您将此作为官方答案发布,我会接受。 C++11 模式下的 GCC 也接受这一点,因此它很可能是一个 MSVC 错误。 【参考方案1】:

这确实是 VS2012 编译器中的一个拒绝有效错误,它被函数类型中的参数名称混淆,认为函数类型的参数是模板参数,因此投诉。 C++11 模式下的 G++ 4.8 和 4.9 接受此代码,Clang 3.3 和 ICC 13 也是如此;这是使用Godbolt's interactive compiler 检查的。此外,根据N3337 14.1 (temp.param) p4,对函数的指针和左值引用是允许的,不受函数参数或返回类型的限制:

非类型模板参数应具有以下之一(可选 cv-qualified) 类型:

整数或枚举类型, 指向对象的指针或指向函数的指针, 对对象的左值引用或对函数的左值引用, 指向成员的指针, std::nullptr_t

解决方法是 jrok 在 cmets 中提到的:只需从函数类型中删除参数名称——我能够测试的所有编译器都接受这个。

【讨论】:

以上是关于让函数指针模板参数接受右值引用是不是合法?的主要内容,如果未能解决你的问题,请参考以下文章

右值引用,移动语义,完美转发

如何将右值引用参数传递给 C++ 中的模板 operator() 函数?

C++11 中的左值引用和右值引用的区别

C++0x 右值引用模板参数推导

具有适用于左值和右值的引用参数的 C++ 函数

右值引用成员变量有啥用