jot*_*tik 60 c++ operator-overloading multiple-inheritance ambiguous
template <typename CRTP>
struct Pre {
CRTP & operator++();
};
template <typename CRTP>
struct Post {
CRTP operator++(int);
};
struct Derived
: Pre<Derived>
, Post<Derived>
{};
int main() {
Derived d;
d++;
++d;
}
Run Code Online (Sandbox Code Playgroud)
我从GCC得到这些错误:
<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
d++;
^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
++d;
^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
Run Code Online (Sandbox Code Playgroud)
预减量和后减量运算符会导致类似的错误.Clang没有这样的错误.任何想法可能是错误的或如何解决这个问题?
Sto*_*ica 63
必须首先进行名称查找.在这种情况下的名称operator++.
[basic.lookup](强调我的)
1名查找规则均匀地适用于所有的名称(包括的typedef-名称([dcl.typedef]),命名空间的名称([basic.namespace])和类名([class.name]))的任何地方语法允许在特定规则讨论的上下文中的此类名称.名称查找将名称的使用与该名称的声明([basic.def])相关联.名称查找应该找到名称的明确声明(参见[class.member.lookup]).如果名称查找名称是函数名称,则名称查找可以将多个声明与名称相关联; 据说声明形成一组重载函数([over.load]).在名称查找成功后发生重载分辨率([over.match]).访问规则(Clause [class.access])仅在名称查找和功能重载解析(如果适用)成功时被认为是一次.只有在名称查找之后,函数重载解析(如果适用)和访问检查成功才会在表达式处理(Clause [expr])中进一步使用名称声明引入的属性.
并且只有在查找明确时,才会进行重载解析.在这种情况下,名称在两个不同类的范围内找到,因此即使在重载解析之前也存在歧义.
[class.member.lookup]
8如果明确找到重载函数的名称,则在访问控制之前也会发生重载分辨率([over.match]).通常可以通过使用类名限定名称来解决歧义.[例如:
Run Code Online (Sandbox Code Playgroud)struct A { int f(); }; struct B { int f(); }; struct C : A, B { int f() { return A::f() + B::f(); } };- 结束例子]
该示例几乎总结了[class.member.lookup]之前段落中相当长的查找规则.您的代码存在歧义.海湾合作委员会报告是正确的.
至于解决这个问题,评论中的人已经提出了解决方法的想法.添加帮助程序CRTP类
template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};
struct Derived : PrePost<Derived> {};
Run Code Online (Sandbox Code Playgroud)
该名称现在位于单个类的范围内,并命名两个重载.查找成功,重载解析可能会继续.
| 归档时间: |
|
| 查看次数: |
3528 次 |
| 最近记录: |