This code works on GCC but not 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);
}
Godbolt link: https://godbolt.org/g/qPJ47p
In the case of a private member function, GCC correctly detects the attempt to access a private member if the template function is instantiated, but otherwise does not. Clang detects the attempt even when the template function is never instantiated.
However, when using a private static constexpr variable, GCC (up to the latest 8.1) fails to stop private access even if the template function is instantiated. Clang correctly (?) complains.
Question: which of the two compilers is Standard-compliant in this situation?
It seems to me that GCC can't be right in allowing access to a private static constexpr variable. Yet at the same time it doesn't seem like an overly complicated issue, but it isn't in the latest GCC: that makes it seem intentional.
Much thanks to paxdiablo for his clear and thorough answer. According to his suggestion I've made a more comprehensive list of test cases and narrowed it down to the static
specifier causing the problem for GCC. See this Godbolt link for more detail: 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)
Static member variables It is essentially a global variable, but its name is contained inside a class scope, so it goes with the class instead of being known everywhere in the program. Such a member variable can be made private to a class, meaning that only member functions can access it.
We can access the static member function using the class name or class' objects. If the static member function accesses any non-static data member or non-static member function, it throws an error. Here, the class_name is the name of the class. function_name: The function name is the name of the static member function.
It is possible to declare a data member of a class as static irrespective of it being a public or a private type in class definition. If a data is declared as static, then the static data is created and initialized only once.
This definitely looks like a bug since whether it's an instantiated template function or a real function should have no bearing on accessibility of private members in the base class. If you change your code to:
int bar(int&) {
return PRIVATE;
}
then it rightly complains:
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;
^
I would just raise this as a bug on gcc
. If they do have a different view on its validity, they will let you know about it.
And, for when you do file the bug, I'd suggest using the absolute minimalist example that works, it'll make it much easier for them to debug. I got that down to:
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);
}
You may also want to indicate the various possibilities for declaring PRIVATE
and their effect on gcc
and clang
(trunks as of this question):
gcc clang
-------- --------
static constexpr int accepted rejected
static const int accepted rejected
const int rejected rejected
int rejected rejected
Using a non-templated function instead (as mentioned above):
int bar(int) {
return PRIVATE;
}
seems to result in gcc
"behaving" itself:
gcc clang
-------- --------
static constexpr int rejected rejected
static const int rejected rejected
const int rejected rejected
int rejected rejected
So, if this is indeed a gcc
problem, I'd be thinking that there's some interaction between static
and templates which is causing the issue.
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