如何创建带有前缀长度字节的编译时常量字符串?
How to create compile-time constant string with prepended length byte?
我有一些旧代码使用 #define
来,嗯,定义一些字符串文字,例如
#define FredString "[=10=]4FRED"
我想更新以避免使用 #define
。我得到的最接近的是如下所示:
static constexpr char* FSraw= "FRED";
static constexpr char FSlen= (char)(sizeof(FSraw) - 1);
static constexpr char* FredString= FSlen FSraw;
但是编译器似乎对第三行不满意。
在编译时构造这样一个字符串的最佳方法是什么?显然我仍然可以显式编码长度,但也显然,这更容易出错。
寻找 C++17 或更早版本的解决方案。
template <std::size_t N>
constexpr std::array<char, N+1> AddLenPrefix(const char (&str)[N])
{
std::array<char, N+1> ret{};
ret[0] = N-1; // Exclude the '[=10=]'.
for (std::size_t i = 0; i < N; i++)
ret[i+1] = str[i];
return ret;
}
static constexpr auto FredString = AddLenPrefix("FRED");
你也可以这样:
#include <string_view>
#include <utility>
template <std::string_view const& S, typename>
struct prepend_length_impl;
template <std::string_view const& S, std::size_t ... Is>
struct prepend_length_impl<S, std::index_sequence<Is...>> {
static constexpr const char value[]{ (sizeof...(Is) + '0'), S[Is]..., 0 };
};
template <std::string_view const& S>
struct prepend_length {
static constexpr std::string_view value =
prepend_length_impl<S, std::make_index_sequence<S.size()>>::value;
};
然后像这样使用它:
static constexpr std::string_view raw = "fred";
static constexpr std::string_view fred = prepend_length<raw>::value; // "4fred"
我有一些旧代码使用 #define
来,嗯,定义一些字符串文字,例如
#define FredString "[=10=]4FRED"
我想更新以避免使用 #define
。我得到的最接近的是如下所示:
static constexpr char* FSraw= "FRED";
static constexpr char FSlen= (char)(sizeof(FSraw) - 1);
static constexpr char* FredString= FSlen FSraw;
但是编译器似乎对第三行不满意。
在编译时构造这样一个字符串的最佳方法是什么?显然我仍然可以显式编码长度,但也显然,这更容易出错。
寻找 C++17 或更早版本的解决方案。
template <std::size_t N>
constexpr std::array<char, N+1> AddLenPrefix(const char (&str)[N])
{
std::array<char, N+1> ret{};
ret[0] = N-1; // Exclude the '[=10=]'.
for (std::size_t i = 0; i < N; i++)
ret[i+1] = str[i];
return ret;
}
static constexpr auto FredString = AddLenPrefix("FRED");
你也可以这样:
#include <string_view>
#include <utility>
template <std::string_view const& S, typename>
struct prepend_length_impl;
template <std::string_view const& S, std::size_t ... Is>
struct prepend_length_impl<S, std::index_sequence<Is...>> {
static constexpr const char value[]{ (sizeof...(Is) + '0'), S[Is]..., 0 };
};
template <std::string_view const& S>
struct prepend_length {
static constexpr std::string_view value =
prepend_length_impl<S, std::make_index_sequence<S.size()>>::value;
};
然后像这样使用它:
static constexpr std::string_view raw = "fred";
static constexpr std::string_view fred = prepend_length<raw>::value; // "4fred"