编译时来自字符串的 Char 序列,无需递归
Char sequence from string at compile time WITHOUT recursion
是的,这个话题可能看起来已经被问了一百遍了,但我问的是非常不同的。
请不要让我误解:模板递归在 C++03 中使用时可能很棒,并且是某些习语的唯一方法,但在 MSVS 2017/2019 编译器中使用并获取时可能会出现问题可怕的fatal error C1202: recursive type or function dependency context too complex
.
我知道 gcc 和 clang 管理的递归比 MSVS 好得多,但是这次编译器是一个合同主题,不能更改。
我开始使用 boost::hana::string
,但是对于复杂的字符串(超过 2000 个字符)会出现错误。
我想知道是否有某种方法可以复制 BOOST_HANA_STRING
宏的行为(基本上它接受一个字符串并将其转换为 char 序列,或 wchar 取决于输入字符串)但摆脱递归。
我想付出的代价是完全使用 C++17,而不是使用 fold,但对我来说这是负担得起的。
顺便说一句,请不要提供operator""_cs
解决方案,因为MSVS不兼容这样的gcc扩展。
我想要实现的伪代码:
STRING("Hello")
=> my_static_string<char, 'H', 'e', 'l', 'l', 'o'>
I wonder if there is some way to replicate the behaviour of BOOST_HANA_STRING
macro (basically it takes a string and converts it into a char sequence, or wchar depending of input string) but getting rid of recursion.
好吧,这会很困难,因为 BOOST_HANA_STRING
doesn't use recursion:
namespace string_detail {
template <typename S, std::size_t ...N>
constexpr string<S::get()[N]...>
prepare_impl(S, std::index_sequence<N...>)
{ return {}; }
template <typename S>
constexpr decltype(auto) prepare(S s) {
return prepare_impl(s,
std::make_index_sequence<sizeof(S::get()) - 1>{});
}
}
#define BOOST_HANA_STRING(s) \
(::boost::hana::string_detail::prepare([]{ \
struct tmp { \
static constexpr decltype(auto) get() { return s; } \
}; \
return tmp{}; \
}())) \
注意缺少递归。它只是获取字符串的大小,使用它来构建索引序列,并使用该序列来构建字符串元素的包扩展。它总是恰好是 2 个函数调用深度;不多也不少
你的问题不是递归;您的问题是 Visual Studio 不支持“2000”元素参数包。 C++ 标准只建议编译器支持 1024 个模板参数,Visual C++ support 2046。我不会指望这个数字在未来变得更大,所以你需要找到替代方法来做你在这里做的任何事情。
此外,C++20 允许您创建一个真正的编译时字符串 class,它存储实际字符的实际数组,您可以在正常的实际代码中实际使用这些实际字符,而不是元编程。并且它们可以用作模板参数;一个 单个 模板参数。 VC++ 已经支持这个。
是的,这个话题可能看起来已经被问了一百遍了,但我问的是非常不同的。
请不要让我误解:模板递归在 C++03 中使用时可能很棒,并且是某些习语的唯一方法,但在 MSVS 2017/2019 编译器中使用并获取时可能会出现问题可怕的fatal error C1202: recursive type or function dependency context too complex
.
我知道 gcc 和 clang 管理的递归比 MSVS 好得多,但是这次编译器是一个合同主题,不能更改。
我开始使用 boost::hana::string
,但是对于复杂的字符串(超过 2000 个字符)会出现错误。
我想知道是否有某种方法可以复制 BOOST_HANA_STRING
宏的行为(基本上它接受一个字符串并将其转换为 char 序列,或 wchar 取决于输入字符串)但摆脱递归。
我想付出的代价是完全使用 C++17,而不是使用 fold,但对我来说这是负担得起的。
顺便说一句,请不要提供operator""_cs
解决方案,因为MSVS不兼容这样的gcc扩展。
我想要实现的伪代码:
STRING("Hello")
=> my_static_string<char, 'H', 'e', 'l', 'l', 'o'>
I wonder if there is some way to replicate the behaviour of
BOOST_HANA_STRING
macro (basically it takes a string and converts it into a char sequence, or wchar depending of input string) but getting rid of recursion.
好吧,这会很困难,因为 BOOST_HANA_STRING
doesn't use recursion:
namespace string_detail {
template <typename S, std::size_t ...N>
constexpr string<S::get()[N]...>
prepare_impl(S, std::index_sequence<N...>)
{ return {}; }
template <typename S>
constexpr decltype(auto) prepare(S s) {
return prepare_impl(s,
std::make_index_sequence<sizeof(S::get()) - 1>{});
}
}
#define BOOST_HANA_STRING(s) \
(::boost::hana::string_detail::prepare([]{ \
struct tmp { \
static constexpr decltype(auto) get() { return s; } \
}; \
return tmp{}; \
}())) \
注意缺少递归。它只是获取字符串的大小,使用它来构建索引序列,并使用该序列来构建字符串元素的包扩展。它总是恰好是 2 个函数调用深度;不多也不少
你的问题不是递归;您的问题是 Visual Studio 不支持“2000”元素参数包。 C++ 标准只建议编译器支持 1024 个模板参数,Visual C++ support 2046。我不会指望这个数字在未来变得更大,所以你需要找到替代方法来做你在这里做的任何事情。
此外,C++20 允许您创建一个真正的编译时字符串 class,它存储实际字符的实际数组,您可以在正常的实际代码中实际使用这些实际字符,而不是元编程。并且它们可以用作模板参数;一个 单个 模板参数。 VC++ 已经支持这个。