这个问题涉及 std::ranges::view
类型对象作为类的成员变量。我试图更好地理解它们,所以我可能会在这里编写一些糟糕的代码!
假设我们有一个函数 foo()
它与某些数据源交互并返回 std::tuple
范围 View 数:
auto foo(int i)
{
auto v1 = views::iota(i) | views::transform([](int i){ return i++; });
auto v2 = views::iota(i) | views::filter([](int i){ return i % 2; });
auto v3 = views::iota(i) | views::transform([](int i){ return i += 3; });
return std::make_tuple(v1,v2,v3);
}
然后我们需要做一些处理,其中涉及 foo()
的三个返回 View ,它们之间存在一定的相互依赖关系。因此,我想将它们存储为类的成员,但我想避免复制整个底层数据,所以我这样做:
template<ranges::view Vx, ranges::view Vy, ranges::view Vz>
struct Processor
{
public:
Processor(Vx&& x, Vy&& y, Vz&& z) : m_x{x}, m_y{y}, m_z{z} {}
auto bar() { /* work using m_x, m_y and m_z */ }
private:
Vx m_x;
Vy m_y;
Vz m_z;
};
在这种情况下,我必须初始化 Processor
的实例使用std::move
,像这样:
auto [x,y,x] = foo(10);
Processor p(std::move(x), std::move(y), std::move(z));
或者,我选择 x
, y
和z
按 Processor
构造函数中的值即Processor(Vx x, Vy y, Vz z) : m_x{x}, m_y{y}, m_z{z} {}
然后可以构造一个实例:
auto [x,y,x] = foo(10);
Processor p(x, y, z);
所以,我想澄清一下(a)这是否是一个好主意以及(b)我应该对这两种方法采取哪种方法?我怀疑按值传递是正确的(值语义,对吧?),因为我们不复制底层数据,只复制每个数据的 View 。
最后有没有办法约束Processor
的模板参数此外,例如写类似 ranges::view<int>
的内容当我将每个范围传递给构造函数时,我是否知道它的基础类型?
谢谢!神 bolt 链接:https://godbolt.org/z/Gx419949n
最佳答案
View 通常按值传递,因为通常它不拥有数据,它只是保留指向数据的指针(当然也有一些异常(exception),例如single_view
),因此处理器(Vx x, Vy y, Vz z)
应该是首选。
但是,请务必注意, View 仅保证可移动。例如,标准 owning_view
是仅移动 View ,因此您应该确保将值移动到成员初始值设定项列表中的成员
template<ranges::view Vx, ranges::view Vy, ranges::view Vz>
struct Processor
{
public:
Processor(Vx x, Vy y, Vz z)
: m_x{std::move(x)}, m_y{std::move(y)}, m_z{std::move(z)} {}
private:
Vx m_x;
Vy m_y;
Vz m_z;
}
Finally, is there any way to constrain the template parameters of
Processor
further, for example writing something like ranges::view if I know the underlying type of each range when I pass it to the constructor?
您可以使用requires子句进行额外的约束检查
template<ranges::view Vx, ranges::view Vy, ranges::view Vz>
requires std::same_as<std::ranges::range_value_t<Vx>, int> &&
std::same_as<std::ranges::range_value_t<Vy>, int> &&
std::same_as<std::ranges::range_value_t<Vz>, int>
struct Processor {
// ...
};
关于c++ - 将 std::ranges::view 类型对象传递给类的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75548823/