gpt4 book ai didi

子 vector 和成员的 C++ 编译时解释

转载 作者:行者123 更新时间:2023-11-30 03:30:13 25 4
gpt4 key购买 nike

我有一个粒子类,用于保存对象的位置、速度和加速度。我可以通过 .position().velocity().acceleration() 访问 vector 的相关部分。我还可以访问每个单独的数字,如 .velocity_x().velocity_y().velocity_z() 等我想要的要做的是以这种方式访问​​速度的 z 部分:

p.velocity().z()

我想同时使用 .velocity()(作为子 vector )和 .velocity().z()(作为单个数字)时间。

我还想避免定义任何额外的变量。我更喜欢在编译时解释所有内容(由于性能优先)。

这个实现在c++中可行吗?

在一次尝试中,我考虑过返回另一个带有仿函数的类。但是除了编译时解释的问题之外,const 还存在一个问题,因为 .velocity() 不知道它后面是否会跟一个 const.z() 的非 const 形式。

#include <iostream>
#include <armadillo>

class Particle
{
public:
arma::vec::fixed<9> data;

inline double velocity_z() const
{
return data(5);
}
inline double& velocity_z()
{
return data(5);
}

inline const arma::subview_col<double> position() const
{
return data.subvec(0,2);
}
inline arma::subview_col<double> position()
{
return data.subvec(0,2);
}
inline const arma::subview_col<double> velocity() const
{
return data.subvec(3,5);
}
inline arma::subview_col<double> velocity()
{
return data.subvec(3,5);
}
inline const arma::subview_col<double> acceleration() const
{
return data.subvec(6,8);
}
inline arma::subview_col<double> acceleration()
{
return data.subvec(6,8);
}
};

arma::vec vector3(double x,double y,double z)
{
return {x,y,z};
}

int main()
{
Particle p;
p.position()=vector3(1.1,2.1,3.1);
p.velocity()=vector3(1.2,2.2,3.2);
p.velocity_z()=10.0;
p.acceleration()=vector3(1.3,2.3,3.3);
p.data.print();
return 0;
}


// output:

// 1.1000
// 2.1000
// 3.1000
// 1.2000
// 2.2000
// 10.0000
// 1.3000
// 2.3000
// 3.3000

制作:

g++ -std=c++11 test1.cpp -larmadillo

Armadillo documentation

最佳答案

嗯,一个可能的解决方案是返回一个代理对象,它既公开了 .{x|y|z}() 成员函数,又可以隐式转换为您的 vector 类型。

概念上是这样的:

#include <type_traits>

using vector_t = /* your library type */;

template<bool RValue>
class vector_proxy {
using return_type = typename std::conditional<RValue, vector_t&&, vector_t const&>::type;
vector_t &ref;
public:
vector_proxy(vector_t &ref) : ref(ref) {}
vector_proxy(vector_proxy const&) = delete;
vector_proxy& operator=(vector_proxy const&) = delete;
vector_proxy(vector_proxy&&) = delete;
vector_proxy& operator=(vector_proxy&&) = delete;

auto x() { /* code to produce x */ }
auto y() { /* code to produce y */ }
auto z() { /* code to produce z */ }

operator return_type() { return static_cast<return_type>(ref); }
};

为什么要模板?因为我想你会想要不同的行为,这取决于粒子对象的值类别。

如果粒子是左值,我们不想返回对粒子内部数据的非常量引用。如果它是一个右值,我们也可以返回一个右值引用,这样代码的行为就“符合预期”。

粒子的成员函数 velocity() 可以有一个值类别限定符来区分这两种情况。上面的模板只是捕获了共同的行为并抽象了差异。

class particle {
// Members
public:
vector_proxy<false> velocity() const& { return {/* A ref to the velocity member */}; }
vector_proxy<true> velocity() && { return {/* A ref to the velocity member */}; }

// More functionality
};

自从您在评论中阐明 velocity 总是按值返回一个新的 vector 对象(顺便说一句,这是一种很好的默认方法),同时也允许修改粒子。上面的解决方案需要更新:

class particle;

template<bool ByRef>
class vector_proxy {
using return_type =
typename std::conditional<ByRef, double&, double>::type;

using ref_type =
typename std::conditional<ByRef, particle&, particle const&>::type;

ref_type ref;
public:
vector_proxy(ref_type ref) : ref(ref) {}
vector_proxy(vector_proxy const&) = delete;
vector_proxy& operator=(vector_proxy const&) = delete;
vector_proxy(vector_proxy&&) = delete;
vector_proxy& operator=(vector_proxy&&) = delete;

return_type x();
return_type y();
return_type z();

operator vector_t();
};

class particle {
// Members

template<bool>
friend class vector_proxy;
public:
vector_proxy<false> velocity() const { return {*this}; }
vector_proxy<true> velocity() { return {*this}; }

// More functionality
};

template<bool ByRef>
auto vector_proxy<ByRef>::x -> return_type {
return ref.data(3);
}

template<bool ByRef>
auto vector_proxy<ByRef>::y -> return_type {
return ref.data(4);
}

template<bool ByRef>
auto vector_proxy<ByRef>::z -> return_type {
return ref.data(5);
}

template<bool ByRef>
vector_proxy<ByRef>::operator vector_t() {
return ref.data.subvec(3, 5)
}

应该就是这样。

关于子 vector 和成员的 C++ 编译时解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45158481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com