2

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>

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); // error here
        static_assert(length == 3, "error");
        
    public :
        static void f()
        {
            std::cout << length << std::endl;
        }
};
        
int main()
{
    Test::f();
}

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?

3
  • 2
    Are you strings always initialized as char str[] = "..."? Because you could get the length simply as sizeof(str)-1 in this form. Commented Oct 2, 2016 at 18:25
  • 1
    @kennytm: except, that doing so can produce wrong results. For example, sizeof("abc\0def") - 1 yields 7 while the constStrLength() function would yield 3. Commented Oct 2, 2016 at 18:27
  • 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 ;) Commented Oct 2, 2016 at 18:44

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh, I thought that declaring the function as static would have defined it directly. Thanks for help, that solves my problem (I will use the base class hack)
@AntoineMorel: I think the relevant section is 9.2 [class.mem] paragraph 2: A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, using-declarations introducing inheriting constructors (12.9), exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.