- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
根据 this problem ,我们可以使用 C++20 的 std::views::split
将 std::string_view
拆分为 std::string_view
的范围:
std::string_view s = "this should be split into string_views";
auto views = s | std::views::split(' ')
| std::views::transform([](auto&& rng) {
return std::string_view(&*rng.begin(), std::ranges::distance(rng));
});
如果我想将那些 std::string_view
存储到一些类似元组的对象中,例如 Boost.Fusion.Sequence
、std::tuple
,或 std::array
:
// magic function
auto tuple_like = to_tuple_like(views);
我该怎么做?有没有不需要创建像 std::vector
这样的中介的解决方案?请注意,原点 s
不是 constexpr
。
最佳答案
这里是“魔术函数”的示例实现,可将您的 View 转换为字符串 View 的元组
#include <iostream>
#include <algorithm>
#include <array>
#include <ranges>
#include <string_view>
#include <tuple>
template <std::size_t tup_size>
struct TupleType {
};
/*
must be manually defined for each size you want to support
*/
template <>
struct TupleType<6> {
using type = std::tuple<
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view>;
};
template <>
struct TupleType<7> {
using type = std::tuple<
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view>;
};
template <std::size_t idx, class Tup, class It>
constexpr void TupleAssignImpl(Tup& tup, It& it) {
std::get<idx>(tup) = *it;
++it;
}
template <class Tup, class It>
constexpr void AssignEachImpl(Tup& tup, It& it) {
}
template <std::size_t idx, std::size_t ... Is, class Tup, class It>
constexpr void AssignEachImpl(Tup& tup, It& it) {
TupleAssignImpl<idx>(tup, it);
AssignEachImpl<Is...>(tup, it);
}
template <class Tup, class It, std::size_t ... Is>
constexpr void AssignEach(Tup& tup, It& it, std::index_sequence<Is...>) {
AssignEachImpl<Is...>(tup, it);
}
template <std::size_t size, class Range>
constexpr auto ToTuple(Range const& rng) {
auto tup = typename TupleType<size>::type{};
auto it = std::ranges::begin(rng);
AssignEach(tup, it, std::make_index_sequence<size>{});
return tup;
}
int main() {
constexpr std::string_view s = "this should be split into string_views";
constexpr auto views = s | std::views::split(' ')
| std::views::transform([](auto&& rng) {
return std::string_view(&*rng.begin(), std::ranges::distance(rng));
});
constexpr auto sz = std::distance(
std::ranges::begin(views),
std::ranges::end(views));
auto tup = ToTuple<sz>(views);
static_assert(std::is_same_v<decltype(tup), std::tuple<
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view,
std::string_view>>);
std::cout << std::get<0>(tup) << std::endl;
std::cout << std::get<1>(tup) << std::endl;
std::cout << std::get<2>(tup) << std::endl;
std::cout << std::get<3>(tup) << std::endl;
std::cout << std::get<4>(tup) << std::endl;
std::cout << std::get<5>(tup) << std::endl;
}
输出:
this
should
be
split
into
string_views
一些评论:
一般来说,可能有(很可能是)更好的方法来实现这一点。这只是我的方法。
我觉得必须为要支持的每种大小的元组手动定义 TupleType
的特化有点笨拙。尽管由于在编译时必须严格知道元组的类型,所以我不知道另一种方法。
有了 AssignEach
,我宁愿写一个简单的 for 循环。例如
for (std::size_t i = 0; i < size; ++i) {
std::get<i>(tup) = *it;
++it;
}
但当然 std::get
的参数必须在编译时严格知道,所以我使用 AssignEach
作为解决方法。
元组的大小必须作为模板参数提供给 ToTuple
,因为,为了正常工作,我们必须保证在编译时知道元组的大小。
作为最后的说明:正如其他人所指出的,也许使用 std::tuple
而不是同质范围的调用在这里是有问题的。但是你问如何做到,这是一种方法。
编辑:
如果您可以使用类似元组的 std::array
,则该方法会简单得多。不需要 TupleType
和 AssignEach
解决方法的专门化。
#include <iostream>
#include <algorithm>
#include <array>
#include <ranges>
#include <string_view>
template <std::size_t size, class Range>
constexpr auto ToTuple(Range const& rng) {
auto array = std::array<std::string_view, size>{};
std::copy(std::ranges::begin(rng), std::ranges::end(rng),
array.begin());
return array;
}
int main() {
constexpr std::string_view s = "this should be split into string_views";
constexpr auto views = s | std::views::split(' ')
| std::views::transform([](auto&& rng) {
return std::string_view(&*rng.begin(), std::ranges::distance(rng));
});
constexpr auto sz = std::distance(
std::ranges::begin(views),
std::ranges::end(views));
auto tup = ToTuple<sz>(views);
for (const auto str : tup) {
std::cout << str << std::endl;
}
}
注意:输出与元组示例相同
关于split - 如何使用 C++20 std::views::split 将 std::string_views 拆分为类似元组的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63045426/
我是一名优秀的程序员,十分优秀!