用于嵌套私有枚举的运算符++——哪个编译器是正确的?

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

基本上,我希望能够为 Test 枚举定义 operator++,它是内部 class 的私有成员,是外部 class 的私有成员。此代码段可能有助于理解我想要实现的目标:

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 是在 private Inner class 中定义的,所以我必须将两个 class 加为好友,尽管这没有意义(我不想要访问外部 class 中的测试枚举。只是为了能够在内部 class)

中使用 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 文件中包含的神奇附加逻辑。我应该如何正确声明 operator++ 才能对 Test 枚举进行运算?

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

编辑: 把霍尔特的评论带到这里: "Actually, clang accepts your second code (with the two friend declaration), which would be the standard way. Whether this is a clang extension or a g++ bug I don't know... Maybe you should reformulate your question to get the attention of some language-lawyer around there ;)" 也许更合适的问题是,gcc 和 msvc(我试过)是否允许双重友谊代码是否正确,因为在我看来,C++ 标准应该以某种方式允许干净的编码像这样的案例(其实没那么复杂)

您要声明的是一个 "global" 函数 (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;
}