GCC允许访问私有静态成员

Ant*_*ton 11 c++ gcc clang

此代码适用于GCC,但不适用于clang.

class Base
{
    static constexpr int PRIVATE = 1;
};

struct Derived : public Base
{
    template <class T>
    int bar( T & t )
    {
        return PRIVATE;
    }
};

int main()
{
    Derived d;
    int i = 3;
    d.bar(i);
}
Run Code Online (Sandbox Code Playgroud)

Godbolt链接:https://godbolt.org/g/qPJ47p

在私有成员函数的情况下,如果模板函数被实例化,GCC正确地检测访问私有成员的尝试,否则不会.即使从未实例化模板函数,Clang也会检测到该尝试.

但是,当使用私有静态constexpr变量时,即使模板函数被实例化,GCC(最新的8.1)也无法停止私有访问.Clang正确(?)抱怨.

问题:在这种情况下,两个编译器中的哪一个符合标准?

在我看来,GCC在允许访问私有静态constexpr变量方面是不对的.然而同时它似乎不是一个过于复杂的问题,但它不是最新的海湾合作委员会:这似乎是故意的.

非常感谢paxdiablo的清晰彻底的回答.根据他的建议,我已经制作了一个更全面的测试用例列表,并将其缩小到static导致GCC问题的说明符.有关更多详细信息,请参阅Godbolt链接:https://godbolt.org/g/A3zCLk

Comparison of GCC and Clang:

Private member    | GCC         | Clang

static const      | accept      | reject
static constexpr  | accept      | reject
static            | accept      | reject
const             | instantiate | reject
no-specifiers     | instantiate | reject
static function   | instantiate | reject
function          | instantiate | reject

("instantiate" means GCC rejects it upon template instantiation)
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 7

肯定看起来像一个bug,因为它是一个实例化的模板函数还是一个真正的函数应该对基类中私有成员的可访问性没有影响.如果您将代码更改为:

int bar(int&) {
    return PRIVATE;
}
Run Code Online (Sandbox Code Playgroud)

然后它正确地抱怨:

testprog.cpp: In member function 'int Derived::bar(int&)':
testprog.cpp:3:26: error: 'constexpr const int Base::PRIVATE' is private
     static constexpr int PRIVATE = 1;
                          ^
testprog.cpp:9:16: error: within this context
         return PRIVATE;
                ^
Run Code Online (Sandbox Code Playgroud)

我只是提出这个问题gcc.如果他们这样做有它的有效性有不同的看法,他们会让你知道.

而且,当你确实提交错误时,我建议使用有效的绝对极简主义示例,这将使它们更容易调试.我明白了:

class Base {
    static constexpr int PRIVATE = 42;
};
struct Derived : public Base {
    template <class T> int bar(T) {
        return PRIVATE;
    }
};
int main() {
    Derived d;
    return d.bar(1);
}
Run Code Online (Sandbox Code Playgroud)

您可能还需要指明声明的各种可能性PRIVATE及其对影响gccclang(树干作为这个问题的):

                                gcc       clang
                              --------   --------
static constexpr int          accepted   rejected
static const int              accepted   rejected
const int                     rejected   rejected
int                           rejected   rejected
Run Code Online (Sandbox Code Playgroud)

使用非模板化函数(如上所述):

int bar(int) {
    return PRIVATE;
}
Run Code Online (Sandbox Code Playgroud)

似乎导致gcc"行为"本身:

                                gcc       clang
                              --------   --------
static constexpr int          rejected   rejected
static const int              rejected   rejected
const int                     rejected   rejected
int                           rejected   rejected
Run Code Online (Sandbox Code Playgroud)

所以,如果这确实是一个gcc问题,我会认为static导致问题的模板和模板之间存在一些交互.