0

I want to do something on strings in the compile-time, so I wrote a class with non-type parameters. Detail is below.

This is my code, compiled by Clang 11.0.1, C++20

#include <type_traits>

// my non-type template parameters string class
template<char... str>
struct StaticString
{
    static constexpr char data[] = { str... };
};

// I will do something in this function, but now just return the character.
template<std::size_t N>
constexpr char nthChar(const char (&str)[N], std::size_t i) { return str[i]; }

// success to compile
inline constexpr char testNthChar = nthChar("xxx", 2);

template<std::size_t N, std::size_t... i>
constexpr auto makeStaticString(const char (&str)[N], std::index_sequence<i...>)
{
    return StaticString<nthChar(str, i)...>{};
    //                    ^~~~~~~~~~~~~~~
    // error: non-type template argument is not a constant expression
    // I tend to think that I made a mistake...
}

template<std::size_t N>
constexpr auto buildStr(const char(&str)[N])
{
    // make an index sequence that is used to provide an index to get chars in str
    return makeStaticString(str, std::make_index_sequence<N>{}).data;
}

extern const char sf[] = "1234";

void foo()
{
    constexpr auto ss = buildStr("0123");

    // not caused by internal linkage attribute
    // constexpr auto ssExtern = buildStr(sf);
}

The full compiler error:

[build] D:\LLVM\bin\clang++.exe   -g -Xclang -gcodeview -O0 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -std=gnu++20 -MD -MT CMakeFiles/test.dir/test.cpp.obj -MF CMakeFiles\test.dir\test.cpp.obj.d -o CMakeFiles/test.dir/test.cpp.obj -c ../test.cpp
[build] ../test.cpp:21:22: error: non-type template argument is not a constant expression
[build]         return StaticString<nthChar(str, i)...>{};
[build]                             ^~~~~~~~~~~~~~~
[build] ../test.cpp:27:9: note: in instantiation of function template specialization 'makeStaticString<4, 0>' requested here
[build]         return makeStaticString(str, std::make_index_sequence<1>{}).data;
[build]                ^
[build] ../test.cpp:33:22: note: in instantiation of function template specialization 'buildStr<4>' requested here
[build]         constexpr auto ss = buildStr("123");
[build]                             ^
[build] ../test.cpp:21:30: note: function parameter 'str' with unknown value cannot be used in a constant expression
[build]         return StaticString<nthChar(str, i)...>{};
[build]                                     ^
[build] 1 error generated.

So my question is, possible to expand the template parameters pack to non-type template arguments, or what is the mistake I made? I would appreciate your help!

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Joker
  • 1
  • 1

0 Answers0