ref-qualified成员函数作为模板参数?

时间:2013-09-11 16:11:38

标签: c++ templates c++11 member-functions ref-qualifier

这在铿锵3.3中编译得很好:

template <typename T>
struct M;

template <typename R, typename C, typename... A>
struct M <R (C::*)(A...)> { };

template <typename R, typename C, typename... A>
struct M <R (C::*)(A...) &> { };

但在gcc 4.8.1中失败:

[...] error: redefinition of ‘struct M <R (C::*)(A ...)>’
 struct M <R (C::*)(A...) &> { };
        ^
[...] error: previous definition of ‘struct M <R (C::*)(A ...)>’
 struct M <R (C::*)(A...)> { };
        ^

在不同的上下文中使用时,会导致各种意外的编译器行为,如崩溃或内部编译器错误。

我理解ref-qualified成员函数在标准中被称为“* this的右值引用”(N2439),并且是supported by gcc 4.8.1

这里的问题是将它们用作模板参数,其中gcc似乎不区分ref-qualified和普通成员函数类型。

clang的std库实现似乎检测

是否支持此功能
__has_feature(cxx_reference_qualified_functions)

那么,这是使用ref-qualified函数标准还是语言扩展?

1 个答案:

答案 0 :(得分:3)

根据8.3.5 [dcl.fct]第6段(我在引用的文字中添加了一些亮点):

  

返回类型,参数类型列表, ref-qualifier 和cv-qualifier-seq,但不是默认参数(8.3.6)或异常规范(15.4) ),是函数类型的一部分

也就是说,ref-qualifier肯定是该类型的一部分。根据8.4.1 [dcl.fct.def.general]第5段,您可以创建指向成员的指针,包括引用限定符:

  

cv-qualifier-seq或 ref-qualifier (或两者)可以是非静态成员函数声明的一部分,非静态成员函数定义或仅指向成员函数的指针(8.3.5);见9.3.2。

没有特定限制,指向具有ref-qualifier的成员函数的指针不能用作非类型模板参数。也就是说,我认为您尝试使用的部分特化应该可行。然而,支持ref-qualifiers在clang和gcc中都是一个相当新的特征,也就是说,可能并非所有的角落情况都被解决了。我尝试使用gcc(20130811)和clang(trunk 190769)的最近快照拍摄上面的剪辑,并且都编译了代码OK。当然,这个片段并没有真正做任何事情,我没有试图滥用这个功能。我猜你刚刚触发了一些编译器错误,我确信这两个项目都会欣赏针对最新快照的错误报告。