这是我尝试在 C++26(我知道,没有发布,但这是我给 gcc 的选项)和 GCC 14.2 中的编译时解析器实现的简化示例。
#include <iostream>
#include <ranges>
#include <string_view>
#include <vector>
using namespace std::string_view_literals;
template <class To>
inline constexpr auto static_caster = []<class From>(From &&from) -> To
requires requires { static_cast<To>(std::declval<From>()); }
{ return static_cast<To>(std::forward<From>(from)); };
struct Test {
bool value;
constexpr Test(const std::string_view input) {
const std::vector<std::string_view> lines =
input | std::views::split('\n') |
std::views::transform(static_caster<std::string_view>) |
std::ranges::to<std::vector>();
// const std::string_view line = lines.at(0);
for (const std::string_view line : lines) {
const std::vector<std::string_view> line_tokens =
line | std::views::split(' ') |
std::views::transform(static_caster<std::string_view>) |
std::ranges::to<std::vector>();
const std::string_view kind = line_tokens.at(0);
this->value = "v" == kind;
}
}
};
int main(int argc, char *argv[]) {
constexpr bool value = Test("v 1.0 2.0 3.0\n"sv).value;
std::cout << value;
return 0;
}
错误信息:
In file included from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/vector:68,
from <source>:4:
/opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/stl_vector.h: In function 'int main(int, char**)':
<source>:33:52: in 'constexpr' expansion of 'Test(std::literals::string_view_literals::operator""sv(((const char*)"v 1.0 2.0 3.0\012"), 14))'
<source>:26:57: in 'constexpr' expansion of 'line_tokens.std::vector<std::basic_string_view<char> >::at(0)'
/opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/stl_vector.h:1333:16: in 'constexpr' expansion of '((const std::vector<std::basic_string_view<char> >*)this)->std::vector<std::basic_string_view<char> >::_M_range_check(__n)'
/opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/stl_vector.h:1292:35: error: call to non-'constexpr' function 'void std::__throw_out_of_range_fmt(const char*, ...)'
1292 | __throw_out_of_range_fmt(__N("vector::_M_range_check: __n "
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1293 | "(which is %zu) >= this->size() "
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1294 | "(which is %zu)"),
| ~~~~~~~~~~~~~~~~~~
1295 | __n, this->size());
| ~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/new_allocator.h:35,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/x86_64-linux-gnu/bits/c++allocator.h:33,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/string:45,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/locale_classes.h:42,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/ios_base.h:43,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/ios:46,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/ostream:42,
from /opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/iostream:43,
from <source>:1:
/opt/compiler-explorer/gcc-trunk-20241219/include/c++/15.0.0/bits/functexcept.h:82:3: note: 'void std::__throw_out_of_range_fmt(const char*, ...)' declared here
82 | __throw_out_of_range_fmt(const char*, ...) __attribute__((__noreturn__,__cold__))
| ^~~~~~~~~~~~~~~~~~~~~~~~
这个示例不起作用,但是带有内部 for 循环的示例仅将其内容与索引 0 处的固定行一起使用。
有趣的是,当我从常量中删除
\n
时,它就起作用了。
问题是为什么以及如何解决这个问题?
这个问题与花哨的 c++26 东西无关,它是一个简单(但很容易错过)的错误。如果您以
\n
结尾并在 \n
上拆分,您将得到一个空行。该空行将包含一个空标记。并且空字符串没有“第 0”元素。如果彼此之间有两个空格,也会出现该错误。
要解决此问题,您可以在转换为
std::views::filter([](auto&& x){return !x.empty();}) |
之前在两个循环中添加 vector
以过滤掉空字符串,因为它们不是标记。