1
votes

I'm trying to play around with constexpr and static_assert. I actually need to check the length of a constexpr string, which is calculated by a dedicated function. Here is what I'm trying to run :

#include <iostream>
using namespace std;

class Test
{
    private :
        static constexpr char str[] = "abc";

        static int constexpr constStrLength(const char* str)
        {
            return *str ? 1+constStrLength(str+1) : 0;
        }
        static constexpr int length = constStrLength(str);
        static_assert(length ==3, "error");

    public :
        static void f()
        {
            cout << len << endl;
        }
};

int main()
{
    Test::f();
    return 0;
}

And here is the error I get :

error: 'static constexpr int Test::constStrLength(const char*)' called in a constant expression static constexpr int len = constStrLength("length ");

What's the right way to achieve it ?

Thanks for help !

1
Are you strings always initialized as char str[] = "..."? Because you could get the length simply as sizeof(str)-1 in this form.kennytm
@kennytm: except, that doing so can produce wrong results. For example, sizeof("abc\0def") - 1 yields 7 while the constStrLength() function would yield 3.Dietmar Kühl
My string is always defined like this, but indeed I need to prevent wrong behavior involving \0 character inside the string. But thanks for the tip ;)Antoine Morel

1 Answers

6
votes

A constexpr function used as a constexpr function needs to be defined at the point of use. However, when you use constStrLength() to define length it is only declared: member function defined within the class definition are actually only declared within the class definition! Their definition becomes available right after the class definition, i.e., informally speaking right after the closing parenthesis.

The fix is to define constStrLength() prior to its use, e.g., as a non-member function or by defining it in a base class.