文字 charT 数组
literal charT array
我正在研究一些 API 涉及文本的算法。
我想让它不依赖于字符类型 (char
,wchar_t
...),所以我制作了带有模板参数 CharT 的模板 类。
这些 类 使用 std::basic_string<CharT>
.
我必须用默认值初始化很多 basic_string。
如果 CharT
是 char
我可以影响文字 "default_text",或者如果 CharT 是 wchar_t
我可以影响 L"default_text",但这不是通用的(它是CharT
家属)。
你有没有想到用通用方法初始化 basic_string 的方法?
如果有帮助,我的代码在 C++11
.
由于你的代码是通用的,我猜你的文字只包含 ASCII 字符。否则,您必须即时对其进行转码,这会很麻烦。为了将 char[]
类型的 pure-ASCII 字符串文字提升为另一种字符类型,您可以简单地单独提升每个字符。
如果您要初始化一个 std::basic_string
,您也可以立即进行。以下函数采用 char[]
字符串文字和目标类型并将其提升为该类型的字符串。
template <typename CharT>
auto
as_string(const char *const text)
{
const auto length = std::strlen(text);
auto string = std::basic_string<CharT> {};
string.resize(length);
for (auto i = std::size_t {}; i < length; ++i)
string[i] = CharT {text[i]};
return string;
}
可以这样用
std::cout << as_string<char>("The bats are in the belfry") << '\n';
std::wcout << as_string<wchar_t>("The dew is on the moor") << L'\n';
但是您要求的是字符数组,而不是 std::basic_string
。在 C++14 中,constexpr
对此有很大帮助。请注意,您需要最新的编译器才能很好地支持它。
我们要做的第一件事是推出我们自己的 std::array
版本,它提供 constexpr
操作。你可以随心所欲,但我会在这里保持简单。
template <typename T, std::size_t N>
struct array { T data[N]; };
接下来,我们还需要一个constexpr
版本的std::strlen
。
template <typename CharT>
constexpr auto
cstrlen(const CharT *const text) noexcept
{
auto length = std::size_t {};
for (auto s = text; *s != CharT {0}; ++s)
++length;
return length;
}
现在我们可以编写一个 constexpr
函数来提升我们的字符串文字。
template <typename CharT, std::size_t Length>
constexpr auto
as_array(const char *const text)
{
auto characters = array<CharT, Length + 1> {};
if (cstrlen(text) != Length)
throw std::invalid_argument {"Don't lie about the length!"};
for (auto i = std::size_t {}; i < Length; ++i)
characters.data[i] = text[i];
characters.data[Length] = CharT {0};
return characters;
}
将它包装成一个宏可能会很方便。我很抱歉。
#define AS_ARRAY(Type, Text) as_array<Type, cstrlen(Text)>(Text).data
可以这样用
std::cout << AS_ARRAY(char, "The bats are in the belfry") << '\n';
std::wcout << AS_ARRAY(wchar_t, "The dew is on the moor") << L'\n';
我正在研究一些 API 涉及文本的算法。
我想让它不依赖于字符类型 (char
,wchar_t
...),所以我制作了带有模板参数 CharT 的模板 类。
这些 类 使用 std::basic_string<CharT>
.
我必须用默认值初始化很多 basic_string。
如果 CharT
是 char
我可以影响文字 "default_text",或者如果 CharT 是 wchar_t
我可以影响 L"default_text",但这不是通用的(它是CharT
家属)。
你有没有想到用通用方法初始化 basic_string 的方法?
如果有帮助,我的代码在 C++11
.
由于你的代码是通用的,我猜你的文字只包含 ASCII 字符。否则,您必须即时对其进行转码,这会很麻烦。为了将 char[]
类型的 pure-ASCII 字符串文字提升为另一种字符类型,您可以简单地单独提升每个字符。
如果您要初始化一个 std::basic_string
,您也可以立即进行。以下函数采用 char[]
字符串文字和目标类型并将其提升为该类型的字符串。
template <typename CharT>
auto
as_string(const char *const text)
{
const auto length = std::strlen(text);
auto string = std::basic_string<CharT> {};
string.resize(length);
for (auto i = std::size_t {}; i < length; ++i)
string[i] = CharT {text[i]};
return string;
}
可以这样用
std::cout << as_string<char>("The bats are in the belfry") << '\n';
std::wcout << as_string<wchar_t>("The dew is on the moor") << L'\n';
但是您要求的是字符数组,而不是 std::basic_string
。在 C++14 中,constexpr
对此有很大帮助。请注意,您需要最新的编译器才能很好地支持它。
我们要做的第一件事是推出我们自己的 std::array
版本,它提供 constexpr
操作。你可以随心所欲,但我会在这里保持简单。
template <typename T, std::size_t N>
struct array { T data[N]; };
接下来,我们还需要一个constexpr
版本的std::strlen
。
template <typename CharT>
constexpr auto
cstrlen(const CharT *const text) noexcept
{
auto length = std::size_t {};
for (auto s = text; *s != CharT {0}; ++s)
++length;
return length;
}
现在我们可以编写一个 constexpr
函数来提升我们的字符串文字。
template <typename CharT, std::size_t Length>
constexpr auto
as_array(const char *const text)
{
auto characters = array<CharT, Length + 1> {};
if (cstrlen(text) != Length)
throw std::invalid_argument {"Don't lie about the length!"};
for (auto i = std::size_t {}; i < Length; ++i)
characters.data[i] = text[i];
characters.data[Length] = CharT {0};
return characters;
}
将它包装成一个宏可能会很方便。我很抱歉。
#define AS_ARRAY(Type, Text) as_array<Type, cstrlen(Text)>(Text).data
可以这样用
std::cout << AS_ARRAY(char, "The bats are in the belfry") << '\n';
std::wcout << AS_ARRAY(wchar_t, "The dew is on the moor") << L'\n';