引用限定的成员函数作为模板参数?

Posted

技术标签:

【中文标题】引用限定的成员函数作为模板参数?【英文标题】:ref-qualified member functions as template arguments? 【发布时间】:2013-09-11 16:11:38 【问题描述】:

这在 clang 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 限定的成员函数在标准中被称为“*this 的右值引用”(N2439),并且是 supported by gcc 4.8.1。

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

clang对std库的实现好像检测了这个特性是否被支持

__has_feature(cxx_reference_qualified_functions)

那么,这种使用 ref 限定函数是标准还是语言扩展?

【问题讨论】:

【参考方案1】:

根据 8.3.5 [dcl.fct] 第 6 段(我在引用的文本中添加了一些突出显示):

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

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

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

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

【讨论】:

很清楚,非常感谢!我已经放弃了对这个问题的希望 :-) 所以我应该期望这个功能在我更新 gcc 时能够正常工作,对吧?目前,我已经禁用了 gcc 的这部分代码。从上面提到的clang的检测,我怀疑gcc的支持只是部分的。 @iavr:clang 的检测机制检测该功能在clang 中是否可用!我不确定其他编译器是否 [已经] 支持相同的检测机制。请注意,我尝试的编译器是 not 发布版本:这些只是我从各自的存储库中提取并编译的最新版本。这些版本(gcc-4.9.0 和 clang-3.4)什么时候发布,我不知道。

以上是关于引用限定的成员函数作为模板参数?的主要内容,如果未能解决你的问题,请参考以下文章

成员函数上的 const 引用限定符 [重复]

在模板派生类中,为啥我需要在成员函数中使用“this->”来限定基类成员名称?

泛型成员函数指针作为模板参数

当对象的引用作为参数时,可以直接打点访问该对象的私有成员(c++)

零值初始化&字符串常数作为函数模板参数

C++基础之类和对象二