Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a constexpr method inside another method of the same class in C++

Tags:

c++

As expected, I can compile the sample below without any problems

// first_sample.cpp
struct sample_struct
{
    constexpr int 
    sample_method() 
    { return 5; }
};

int main() 
{
    sample_struct sample_object;
    constexpr int sample_variable = sample_object.sample_method();
    return 0;
}

But i cannot compile the following sample for the reason

'this' is not a constant expression

// second_sample.cpp
struct sample_struct
{
    constexpr int 
    sample_method_first() 
    { return 5; }

    void 
    sample_method_second() 
    {   constexpr int sample_variable = sample_method_first(); 
        /* Do something with sample_variable */ }
};

int main() 
{ return 0; }

I already know how to solve this "problem" so i am not asking for a solution. I am asking for a reasonable explanation why i am allowed to call a constexpr method from a non-constexpr object while i am not allowed to call the same constexpr method inside another method (from non-constexpr 'this').

like image 952
user2464690 Avatar asked Oct 21 '22 06:10

user2464690


1 Answers

In the C++ Standard, [dcl.constexpr]/9:

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. [...] Otherwise, or if a constexpr specifier is used in a reference declaration, every full-expression that appears in its initializer shall be a constant expression.

Now, the compiler implicitly adds a this-> to the member function call, as specified by [expr.call]/1

In the case of an implicit class member access, the implied object is the one pointed to by this. [Note: a member function call of the form f() is interpreted as (*this).f() (see 9.3.1). —end note ]

As jogojapan has pointed out (see chat discussion), in the official C++11 Standard, this may occur as postfix-expression in a class member access as per [expr.const]/2, which is the case here. But the resolution of Issue 1369 disallowed any use of this in constant expressions; however function invocation substitution can allow using this within the context of a constexpr function by replacing it with a prvalue pointer.

The C++14 draft removes the sub-paragraph about function invocation substitution in favour of an exception to [expr.const]/2, explicitly allowing the use of this within the context of a constexpr function (in this case effectively the same as what function invocation substitution allowed).


Well, this isn't very "reasonable" as it doesn't provide the reason why it is specified in this way, it only provides the reason why the compiler rejects it.

like image 197
dyp Avatar answered Oct 24 '22 11:10

dyp