Accessing static class member functions or variables, can be done in two ways: through an object (obj.member_fun()
or obj.member_var
) or through th
Clang seems to be in the right. When accessing a static member with the member access syntax [class.static/1]:
A static member s of class X may be referred to using the qualified-id expression X::s; it is not necessary to use the class member access syntax to refer to a static member. A static member may be referred to using the class member access syntax, in which case the object expression is evaluated.
So s.v()
will cause s
to be evaluated. Now, according to [expr.const/2.11], s
is not a constant expression:
2 An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:
[...]
an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either:
(2.11.1) - it is initialized with a constant expression or
(2.11.2) - its lifetime began within the evaluation of e;
s
doesn't have a preceding initialization with a constant expression, not in the scope of foo
.
If you want to access the static members based of a function parameter, without hard-coding the type, the way forward is std::remove_reference_t<decltype(s)>
. This is accepted by Clang and GCC both:
#include <type_traits>
struct S
{
constexpr static auto s_v = 42;
constexpr static auto v() { return s_v; }
};
constexpr auto foo(S const& s)
{
constexpr auto v = std::remove_reference_t<decltype(s)>::v();
return v;
}
constexpr auto bar(S const& s)
{
constexpr auto v = std::remove_reference_t<decltype(s)>::s_v;
return v;
}
int main() {}
constexpr auto v = s.v(); // ERROR for clang, OK for gcc
I guess it depends on whether you compile in C++11 or C++14 mode. If you look over at cppreference, you will find (emphasis added by me):
A core constant expression is any expression that does not have any one of the following
(...)
6) Thethis
pointer, except if used for class member access inside a non-static member function (until C++14)
6) Thethis
pointer, except in a constexpr function or a constexpr constructor that is being evaluated as part of the expression (since C++14)
So, in C++11, whatever happens inside s.v()
would not be considered a constant expression, since it uses the this
pointer, but it is not a non-static member function (it's static
) accessing a class member.
Per C++14, however, it would be, since it is evaluating a constexpr
function as part of the expression, so the "except if" clause on the "does not have any of" set of rules catches.
Now don't ask me whether that makes any sense or whether anyone is supposed to understand that... :-)