c++ - 不需要括号或引用的成员别名的 C++ 标准方式?
问题描述
假设我们有一个类,也许是一个模板化的固定大小向量:
template <size_t N, typename T>
struct VectorN
{
T values[N];
}
另外,让我们从一开始就明确表示:不允许#define。我想让 x、y、z、w 等名称可以访问值。其中一种方式(“成员函数”方式)是:
T& x()
{
assert(N >= 1);
return values[0];
}
T& y()
{
assert(N >= 2);
return values[1];
}
/* etc */
它有效,高效且正确,但它很丑陋,因为它要求您像这样使用它:
//reference alias way
VectorN<4,double> v;
v.x() = 4.4;
v.y() = 12.32;
删除括号会导致“函数作为左操作数”错误。据我所知,与匿名结构建立联盟并不标准。编译器可以在成员之间填充,从而破坏一切。另外,我不知道如何使它与可变(在编译时已知)大小一起工作,无论如何它似乎很危险:
template <size_t N, typename T>
struct VectorN
{
union
{
T values[N];
struct
{
T x,y,z,w;
}
}
}
另一种方法是将原始值的引用保留为结构中的变量:
template <size_t N, typename T>
struct VectorN
{
T values[N];
T& x, y, z, w;
}
但是它膨胀了我们向量结构的大小,并且出现了另一个问题:如果向量的大小不是 4 怎么办?然后其中一个引用必须是空的,这是可能的,但它有点像癌症和可怕的。使用指针是没用的——它很丑,容易出错,函数方式要好得多。
所以问题是,如何给成员变量做别名,这样它们就可以无缝使用,就像原生结构一样,像这样:
VectorN<3,int> z;
z.x = 0;
z.y = 1;
z.z = 2;
z.w = 3; //fails cause assertion
甚至可以以便携式方式制作吗?
解决方案
我同意 Jarod 关于使用函数调用的可用性/“丑陋”的评论。但只是为了(也对我自己)表明这是可能的,您可以使用隐式转换运算符模拟“无调用”getter。
现在这是否是一个“好主意”是一个非常不同的问题:
template <typename T, std::size_t N, std::size_t I>
struct named_subset {
using value_type = typename T::value_type;
T* p;
static_assert(I < N, "invalid index");
named_subset(T* p) : p{p} {}
operator value_type() { return (*p)[I]; }
named_subset& operator =(value_type const& rhs) {
(*p)[I] = rhs;
return *this;
}
};
template <typename T, std::size_t N>
struct vec_n {
using value_type = T;
T values[N];
named_subset<vec_n, N, 0> x{this};
named_subset<vec_n, N, 1> y{this};
named_subset<vec_n, N, 2> z{this};
named_subset<vec_n, N, 3> w{this};
T& operator [](std::size_t i) { return values[i]; }
};
(上面的接口被简化了,特别是省略了const
重载。)
当然,这会增加结构的大小,因为每个 getter 都需要随身携带一个指向其所有者的指针。我不认为有办法解决这个问题。
推荐阅读
- kotlin - Dagger @Provides in Kotlin
- java - spring-kafka 使用 Avro 序列化/反序列化 org.springframework.messaging.Message 对象
- ssl - 哪个 Kubernetes 入口“获胜”(同一主机的 tls 和多个入口)?
- sed - 是否可以使用 sed 命令替换: ( -> \( 同时 \( -> (
- resolution - 更改显示器分辨率
- python-3.x - 仅在 pycharm 中没有名为“PIL”的模块(在 IDLE 中运行良好)
- android - 布局不会在没有边距的情况下居中
- java - 如何在java中创建一个由类组成的二维数组
- python-3.x - 通过 Python3 在 Linux 中关闭屏幕
- php - 在给定文本中查找 PHP 中特定对象的模式