操作符++用于嵌套私有枚举-哪个编译器是正确的

Operator++ for nested private enum - which compiler is right?

本文关键字:编译器 用于 嵌套 枚举 操作符      更新时间:2023-10-16

基本上,我想要能够为Test enum定义操作符++,这是内部类的私有成员,这是外部类的私有成员。下面的代码片段可能有助于理解我想要实现的目标:

class Outer{
    class Inner{
        enum Test{ONE, TWO, THREE};
    };  
};
const Outer::Inner::Test& operator++(Outer::Inner::Test& test){
    int rawTest = test;
    test = static_cast<Outer::Inner::Test>(++rawTest);
    return test;
}

不幸的是,上面将不会编译错误,测试是私有成员,所以接下来我尝试如下:

#include <iostream>
using namespace std;
class Outer{
    class Inner{
        enum Test{ONE, TWO, THREE}; 
        friend const Test& operator++(Test& test);
    };  
    friend const Inner::Test& operator++(Inner::Test& test);
};
const Outer::Inner::Test& operator++(Outer::Inner::Test& test){
    int rawTest = test;
    test = static_cast<Outer::Inner::Test>(++rawTest);
    return test;
}

这仍然不起作用,因为Test是在私有的内部类中定义的,所以我必须将两个类放在一起,尽管它没有任何意义(我不想在外部类中访问Test enum)。只是为了能够在内部类中使用operator++)

当然我可以像这样让函数内联:

#include <iostream>
using namespace std;
class Outer{
    class Inner{
        enum Test{ONE, TWO, THREE}; 
        friend const Test& operator++(Test& test){
            int rawTest = test;
            test = static_cast<Outer::Inner::Test>(++rawTest);
            return test;
        }
    };  
};

,但我可能不需要这个,因为假设有一些神奇的附加逻辑,我想在。cpp文件中有。我应该如何正确地声明操作符++才能对测试枚举进行操作?

编辑:这肯定不是给定问题的重复,因为我想简单地为嵌套类中的给定enum声明operator++。所提供的重复问题是关于从外部类函数访问内部类的成员。

编辑:下面是霍尔特的评论:实际上,clang接受你的第二段代码(带有两个友元声明),这将是标准的方式。我不知道这是clang扩展还是g++ bug…也许你应该重新提出你的问题,以引起周围语言律师的注意。"也许更合适的问题是,是否正确,gcc和msvc(我尝试过)不允许双重友谊代码,或者不,在我看来,c++标准应该在某种程度上允许在这样的情况下编写干净的代码(实际上不是那么复杂的情况)。

您要声明的是一个"全局"函数(operator++),由于对Test的访问,该函数仅在Outer::Inner内部使用。我不知道这是否可能,但是一个简单的解决方法是回退到Inner的静态方法:

#include <iostream>
class Outer{
    class Inner{
        enum Test{ONE, TWO, THREE}; 
        static Test& pre_inc(Test&);
        friend Test& operator++(Test& test) {
            return pre_inc(test);
        }
    };  
};
auto Outer::Inner::pre_inc(Test& test) -> Test& {
    int rawTest = test;
    test = static_cast<Test>(++rawTest);
    return test;
}