Access static member in constant expressions

Access to static functions or member variables of a class can be performed in two ways: through an object ( obj.member_fun() or obj.member_var ) or through a class ( Class::member_fun() or Class::member_var ). However, in constexpr functions constexpr Clang gives an error when accessing an object and requires the use of class access:

 struct S { constexpr static auto s_v = 42; constexpr static auto v() { return s_v; } }; #define TEST 1 constexpr auto foo(S const& s [[maybe_unused]]) { #if TEST constexpr auto v = sv(); // ERROR for clang, OK for gcc #else constexpr auto v = S::v(); // OK for clang and gcc #endif return v; } constexpr auto bar(S const& s [[maybe_unused]]) { #if TEST constexpr auto v = s.s_v; // ERROR for clang, OK for gcc #else constexpr auto v = S::s_v; // OK for clang and gcc #endif return v; } int main() {} 

Live Example compiled with -std=c++1z and #define TEST 1 for Clang 5.0 SVN with error message:

 Start prog.cc:12:24: error: constexpr variable 'v' must be initialized by a constant expression constexpr auto v = sv(); // ERROR for clang, OK for gcc ^~~~~ prog.cc:22:24: error: constexpr variable 'v' must be initialized by a constant expression constexpr auto v = s.s_v; // ERROR for clang, OK for gcc ^~~~~ 2 errors generated. 1 Finish 

Question : is this a Clang error, or is gcc too liberal in accepting both forms of syntax to access the static member in the constexpr function?

+7
c ++ clang static-members constexpr c ++ 17
source share
2 answers

Klang seems to be in the right direction. When accessing a static element with membership access syntax [class.static / 1] :

A static member of class X may refer to the use of an identifier with the qualification expression X :: s; There is no need to use class member access syntax to reference a static member. A static member can be referenced using the class member access syntax, in which case the expression object is evaluated.

So sv() will call an estimate of s . Now, according to [expr.const / 2.11] , s not a constant expression:

2 The expression e is an expression of a constant constant if the estimate of e, following the rules of an abstract machine, evaluates one of the following expressions:

[...]

An id expression that refers to a variable or link data item type if the link does not have a previous initialization and either:
(2.11.1) - is initialized by a constant expression or (2.11.2) - its lifetime began with an estimate of e;

s does not have previous initialization with a constant expression, not in the scope of foo .


If you want to access static members based on a functional parameter, without hard type coding, the forward path is std::remove_reference_t<decltype(s)> . This is accepted by Clang and GCC:

 #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() {} 
+8
source share
 constexpr auto v = sv(); // ERROR for clang, OK for gcc 

I think it depends on whether you are compiling in C ++ 11 or C ++ 14. If you look at cppreference , you will find (highlighted by me):

Kernel constant expression - any expression that does not have any of the following
(...)
6) The this pointer, unless used to access a member of a class inside a non-static member function (before C ++ 14)
6) The this pointer , with the exception of the constexpr function or the constexpr constructor, which is evaluated as part of the expression (starting with C ++ 14)

So, in C ++ 11, everything that happens inside sv() will not be considered a constant expression, since it uses the this pointer, but it is not a non-static member of function (it static ), access to a member of the class.

Per C ++ 14, however, that would be because it evaluates the constexpr function as part of the expression, so the "except if" clause in the "has no" rule set.

Now don’t ask me if it makes any sense or if someone should understand that ... :-)

0
source share

All Articles