I want to implement string_view multiplied by a number like python ("{}"*8
) so that on fmt::format is simpler to express how many "{}" in format string.
But the following code:
inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
std::array<char, sv.length() * times> result;
constexpr char* data = result.data();
for(int i=0; i<times; ++i){
for(int j=0; j<sv.length(); ++j, ++data){
*data = sv.data()[j];
}
}
return result;
}
The compiler error message is
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:114: error: template argument 2 is invalid
96 | inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
| ^
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:114: error: template argument 2 is invalid
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:114: error: template argument 2 is invalid
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:114: error: template argument 2 is invalid
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:78: error: invalid template-id
96 | inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
| ^~~
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:97: error: use of parameter outside function body before ‘.’ token
96 | inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
| ^
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:114: error: use of parameter outside function body before ‘>’ token
96 | inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
| ^
/home/miki/dumpefs_cpp/include/fs/f3s_spec.h:96:23: error: deduced class type ‘array’ in function return type
96 | inline constexpr auto operator*(const std::string_view& sv, size_t times) -> std::array<char, sv.length() * times> {
| ^~~~~~~~
In file included from /usr/include/c++/11/tuple:39,
from /usr/include/c++/11/bits/unique_ptr.h:37,
from /usr/include/c++/11/memory:76,
from /home/miki/dumpefs_cpp/spdlog-1.11.0/include/spdlog/fmt/bundled/format.h:40,
from /home/miki/dumpefs_cpp/spdlog-1.11.0/include/spdlog/fmt/bundled/compile.h:11,
from /home/miki/dumpefs_cpp/include/fs/f3s_spec.h:23,
from /home/miki/dumpefs_cpp/src/dumpefs.cpp:15:
/usr/include/c++/11/array:95:12: note: ‘template<class _Tp, long unsigned int _Nm> struct std::array’ declared here
95 | struct array
| ^~~~~
Looks like char pointer in constexpr
is not allowed, but how to do char copy? And, when even on function return type std::array<char, sv.length() * times>, the argument 2 is not allowed even they are const?
Below is my c++ compiler:
Function parameters are not constexpr
. so sv.length() * times
cannot be used to define array size.
You need C++20 to allow to return std::string
in constexpr function (even if you cannot have constexpr std::string
):
constexpr auto operator*(const std::string_view& sv, size_t times)
{
std::string result;
for(std::size_t i=0; i<times; ++i){
result += sv;
}
return result;
}
Alternative would be to pass char sequence:
template <char... cs>
struct char_sequence
{
static constexpr char str[sizeof...(cs) + 1] = {cs..., '\0'};
};
template <char... cs1, char... cs2>
constexpr auto operator+(char_sequence<cs1...>, char_sequence<cs2...>)
{
return char_sequence<cs1..., cs2...>{};
}
template <std::size_t N, char... cs>
constexpr auto repeat(char_sequence<cs...>)
{
using seq = char_sequence<cs...>;
return []<std::size_t... Is>(std::index_sequence<Is...>){
return ((static_cast<void>(Is), seq{}) + ...);
}(std::make_index_sequence<N>());
}