Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile surprises when using a string as a template argument

Tags:

c++

c++20

I was playing with strings in templates. I read some interesting blogs and started playing with code.

In the next example, I was able to pass a string literal in a template argument:

#include <algorithm>
#include <iostream>

template<size_t N>
struct StringLiteral {
    constexpr StringLiteral(const char (&str)[N]) {
        // commenting this makes the program to not compile
        std::copy_n(str, N, value);
    }
    constexpr size_t size() const
    {
        return N;
    }

    // changing N to literal, such as 10, makes the program to not compile
    char value[N];
};

template<StringLiteral lit>
void Print() {
    static constexpr auto size = lit.size();
    static constexpr auto contents = lit.value;

    std::cout << "Size: " << size << ", Contents: " << contents << std::endl;
}

int main()
{
    Print<"abc">();
}

Godbolt Link

In this example, I'm passing a string to Print by a template parameter, and it will print the size and value. So far so good.

However, I'm using some features that I don't fully understand, that's probably why I'm so confused.

  1. If I remove std::copy_n(), it doesn't compile. That was very surprising because that code is inside the constructor, N was deduced just before, so I'm not sure why copy_n had these implications.
  2. Changing char value[N] to char value[10] also makes the program invalid. 10 is a literal, so I was expecting the compiler would be able to deduce it without a problem.

Could you clarify what's going on?

like image 567
dmayola Avatar asked Sep 10 '25 18:09

dmayola


1 Answers

Both errors are caused by value remaining partially uninitialized. Adding {} to zero all elements by default is one way to solve this: char value[N]{};.

like image 69
HolyBlackCat Avatar answered Sep 13 '25 08:09

HolyBlackCat