在C ++中是否可以在不使用预处理器的情况下使用不同的名称引用相同的变量?
达到与此伪代码相同的效果
struct vec3f {
float[3] values;
};
struct color : public vec3f {
#define r values[0]
#define g values[1]
#define b values[2]
};
color c;
c.r = 0.5f;
以下具有正确的语义,除了它在结构中为3个引用分配空间:
struct color : public vec3f {
float& r;
float& g;
float& b;
color() : r(values[0]), g(values[1]), b(values[2]) { }
};
有没有办法在不增加struct大小的情况下获得这个编译时名称替换?
答案 0 :(得分:10)
这个怎么样?
struct vec3f {
float[3] values;
};
struct color : public vec3f
{
float& r() { return values[0]; }
float& g() { return values[1]; }
float& b() { return values[2]; }
const float& r() const { return values[0]; }
const float& g() const { return values[1]; }
const float& b() const { return values[2]; }
};
答案 1 :(得分:2)
在这种情况下,我不确定您是否要使用继承。使用普通的union
类型可能会更好:
typedef float vec3f[3];
union color {
vec3f values;
struct {
float r;
float g;
float b;
};
};
color c;
c.values[0] = 10;
assert( c.r == 10 );
答案 2 :(得分:1)
替代方案1
当您需要变量别名时,总是创建一个临时。有了优秀的优化器,您几乎看不到任何性能差异。
struct vec3f
{
float values[3];
};
struct tempvec
{
float &r;
float &g;
float &b;
tempvec( vec3f& bar )
:r(bar.values[0])
, g(bar.values[1])
, b(bar.values[2]){}
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
//when you want to alias values[0] as r do this
tempvec(temp).r = 42;
tempvec(temp).g = 42;
return 0;
}
ALTERNATIVE 2
如果您可以验证平台和操作系统上vec3f
和vec3c
的内存布局是否相同,请考虑 padding/alignment 等。你可以做到
struct vec3f
{
float values[3];
};
struct vec3c
{
float r,g,b;
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
vec3c* alias = reinterpret_cast<vec3c*>(&temp);
alias->r = 4.2f;
alias->g = 4.2f;
alias->b = 4.2f;
return 0;
}
答案 3 :(得分:1)
碰巧,几年前我第一次看到一个非常整洁的trick for this。
这个想法是你按顺序给类命名变量,然后还有一个指向数组的成员类型的static const
成员。重载operator[]
以查找适当的指向成员的指针,使用它从this
中选择成员,并返回引用。
这是有效的,因为指向成员的指针不是普通的指针;他们比那更神奇。 (这使您能够创建到成员函数的非绑定指针,以及为什么它们不能用于需要普通函数指针的地方)。
这也意味着您不必使用任何强制转换技巧,依赖任何类型的对齐,不可移植的匿名联合行为或内存布局保证,您仍然可以参考结构的组件作为命名字段而不是通过访问器函数。