c++language-lawyerconstexprcompile-time-constant

How does C++ handle constexpr evaluation for non-static member function pointers on runtime objects?


The code compiles and runs, but I'm trying to understand how the expression (obj.*funcPtr)(12) can be evaluated at compile-time when obj is not declared as constexpr. I would expect that this might not meet the standard requirements for compile-time evaluation.

#include <iostream>
#include <stdexcept>

template <typename T, size_t N>
class Array
{
public:

    T& operator[](size_t i)
    {
        if (i>=N)
        {
            throw std::out_of_range("Bd index!");
        }
        return data_[i];
    }
    constexpr size_t Size() const
    {
        return N;
    }

private:
    T data_[N]{};
};



class MyClass
{
public:
   constexpr int myFunction(int value)
    {
        return value*2;
    }
};

int main()
{

   constexpr int (MyClass::*funcPtr)(int) = &MyClass::myFunction;
   MyClass obj;
   Array<int ,  (obj.*funcPtr)(12) > arr;
   std::cout << arr.Size() << '\n';

}

Solution

  • The call to the function is a constant expression, because none of the items of [expr.cont]/5 disqualify it from being a constant expression. In particular you are not attempting to perform any problematic lvalue-to-rvalue conversion in the meaning of item 5.9. The only lvalue-to-rvalue conversion you perform is on value, whose lifetime started during the constant expression evaluation, and funcPtr, which is explicitly marked constexpr.

    For an implementation point of view: Your function myFunction doesn't access any data member of obj. So the compiler can determine its result at compile-time from the given argument and doesn't need to care at all about the actual obj instance. Its state has no effect on the result of the function call. The result is always 24.