Static member access in constant expressions

后端 未结 2 1960
一整个雨季
一整个雨季 2020-12-04 01:42

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

相关标签:
2条回答
  • 2020-12-04 01:59

    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() {}
    
    0 讨论(0)
  • 2020-12-04 02:13
    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) The this pointer, except if used for class member access inside a non-static member function (until C++14)
    6) The this 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... :-)

    0 讨论(0)
提交回复
热议问题