尝试访问类的私有成员以防止超载是不正确的?

W.F*_*.F. 7 c++ private-members sfinae type-traits language-lawyer

在尝试创建特征以检查类字段是否公开可用时,我创建了一个代码:

#include <type_traits>
#include <utility>

template <class T, class = void>
struct does_not_have_foo: std::true_type {};

template <class T>
struct does_not_have_foo<T, decltype(std::declval<T>().foo, void())>: std::false_type {};

class Foo {
    int foo;
};

int main() {
    static_assert(does_not_have_foo<Foo>::value);
}
Run Code Online (Sandbox Code Playgroud)

但它似乎未能在[gcc]中编译([clang]似乎在这里更宽松)并出现错误:

prog.cc:8:56: error: 'int Foo::foo' is private within this context
Run Code Online (Sandbox Code Playgroud)

我为我的一些旧代码挖出了类似的东西,归结为以下内容:

template <class T>
auto does_not_have_foo(T t) -> decltype(t.foo, std::false_type()) {
    return {};
}

std::true_type does_not_have_foo(...) { return {}; }

class Foo {
    int foo;
};

int main() {
    static_assert(decltype(does_not_have_foo(Foo{}))::value);
}
Run Code Online (Sandbox Code Playgroud)

它看起来像[gcc][clang]一样完成了它的工作.但是当我在寻找gcc失败的原因时,我发现了一个问题,即每次使用该类私有字段的尝试都是不正确的,因此即使是第二个代码也应该避免.我是在过度解释这个问题,还是第二个代码真的是语言滥用?

Bar*_*rry 6

但它似乎未能在[gcc]中编译([clang]似乎在这里更宽松)

实际上gcc在这里更宽松.gcc bug 59002是一个元bug,它捕获了gcc在访问控制和模板方面的许多错误.对于gcc,在你的第一个场景中,访问Foo::foo很好,即使它是私有的.在您的第二个略有不同的场景中,gcc正确拒绝私有访问.

does_not_have_foo在第一个场景中正确实现,clang正确编译它.只是gcc错误地实现了访问检查.第二种实现同样正确.