6

I have a static_string template

template <std::size_t N>
struct static_string {
    std::array<char, N + 1> elements_; 

    constexpr static_string() noexcept : elements_{} {}

    constexpr static_string(const char (&data)[N + 1]) noexcept {
        for (size_t i = 0; i < N + 1; i++) {
            elements_[i] = data[i];
        }
    }
};

template <std::size_t N>
static_string(const char (&)[N]) -> static_string<N - 1>;

It works fine when use constexpr static_string str1("this is a str");

And I want to construct from a constexpr std::string_view, so I add:

    constexpr static_string(std::string_view sv) noexcept {
        for (size_t i = 0; i < N; ++i) {
            elements_[i] = sv[i];
        }
    }

then if I use

   constexpr std::string_view sv = "this is a str";
   constexpr static_string<sv.size()> str2(sv);

the compiler outputs

<source>: In function 'int main()':
<source>:33:47: error: 'static_string<13>{std::array<char, 14>{std::__array_traits<char, 14>::_Type{'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 's', 't', 'r'}}}' is not a constant expression
   33 |     constexpr static_string<sv.size()> str2(sv);
      |                                               ^
<source>:33:47: error: 'static_string<13>(sv)' is not a constant expression because it refers to an incompletely initialized variable
Compiler returned: 1

So why this expression did not evaluate to a constant, is it possible to construct from constexpr std::string_view? thanks, see https://www.godbolt.org/z/6TToEPnch

1
  • I fixed a minor error and it solved the issue: godbolt.org/z/f1babx1r3. I don't make it an answer, because I don't get why adding the missing null termination also fixes the constexpr issue. Commented Jan 6 at 8:17

1 Answer 1

9

The error message issued by the compiler is misleading.

In fact, the issue is not related to the input string_view but to the fact that elements_ is not fully initialized, which is not allowed in a constexpr constructor
<ref needed
perhaps https://timsong-cpp.github.io/cppwp/n4861/expr.const#11.4

A constant expression is... if the value is an object of class or array type, each subobject satisfies these constraints for the value.

>.

To fix that, just add the missing null terminating character:

#include <array>
#include <iostream>
#include <string_view>

template <std::size_t N>
struct static_string {
    std::array<char, N + 1> elements_;

    constexpr static_string() noexcept : elements_{} {}

    constexpr static_string(const char (&data)[N + 1]) noexcept {
        for (size_t i = 0; i < N + 1; i++) {
            elements_[i] = data[i];
        }
    }

    constexpr static_string(const std::string_view& sv) noexcept {
        for (size_t i = 0; i < N; ++i) {
            elements_[i] = sv[i];
        }
        elements_[N] = '\0';  // completing the initialization of the object
    }
};

template <std::size_t N>
static_string(const char (&)[N]) -> static_string<N - 1>;

int main() {
    constexpr std::string_view sv = "this is a str";
    constexpr static_string str1("this is a str");
    constexpr static_string<sv.size()> str2(sv);
}

LIVE

(btw, you can as well pass the string_view by const reference)

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

7 Comments

really thanks! the fact that elements_ is not fully initialized, now I can use string_view and span, godbolt.org/z/5b9snxE3G
there's little need to pass a string view by const ref, it's already lightweight
@Caleth yes but isn't it better for readability and consistency of API?
No. Would you pass an int or a pointer by const ref?
Pointers aren't fundamental types, they are compound types. int and pointers are object types. I call std::string_view lightweight because it's a non-owning sequence. "A typical implementation holds only two members: a pointer to constant CharT and a size." cppreference
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.