While attempting to create a trait to check whether the class field is publicly available I've created a code:
#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);
}
But it appeared to failed to compile in [gcc] ([clang] seemed to be more permissive here) with an error:
prog.cc:8:56: error: 'int Foo::foo' is private within this context
I dug up for some older code of mine doing something similar which boils down to following:
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);
}
It looked like it done its job in both [gcc] just as well as in [clang]. But when I was looking for a reason of gcc failure I found the question which suggests that every attempt to use of private field of the class is ill-formed and as such even the second code should be avoided. Am I over-interpreting the question or is the second code really the language abuse?
But it appeared to failed to compile in [gcc] ([clang] seemed to be more permissive here)
It's actually gcc that's more permissive here. gcc bug 59002 is a meta-bug that captures the many bugs that gcc has when it comes to access control and templates. To gcc, in your first scenario, accessing Foo::foo
is fine, even though it's private. In your second, slightly different scenario, gcc correctly rejects the private access.
does_not_have_foo
is correctly implemented in the first scenario, clang compiles it correctly. It's just that gcc incorrectly implements access checking. The second implementation is equally correct.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With