Adding references to a class to act as accessors - c++

I have added reference variables to a class to act as accessors for an array which is declared as a private member. Basically, I have something like
class someClass {
private:
int a[3];
public:
int &a0;
int &a1;
int &a2;
someClass() : a0(a[0]), a1(a[1]), a2(a[2]) {}
someClass& operator=(const someClass &other) {
std::memcpy(a, other.a, sizeof(a));
return *this;
}
};
However, it does not work as expected always. What am I missing here? Is there a better way to access elements of a as .a0, .a1, etc.

Instead of using references, you should consider using mixed in unions instead:
struct Vector3
{
union {
float a[3];
struct { float x, y, z; };
struct { float r, g, b; };
};
};
// v.a[0] is an alias for v.x
Vector3 v = { 0.0f, 0.1f, 0.2f };
// you can see this clearly since they have the same address:
std::cout << (&v.a[0] == &v.x) << std::endl;
This should provide what you are actually looking to achieve.

Related

Getting one private member from one class to another

So, I have an algorithm that takes a few sensors, scales them to a temperature and puts the temps in a global data store. However, sensor class A does more calculations that Class B needs. I can't put the new calcs in the data store, and i don't want to include class A inside class B just to get one piece of data with a getter.
Class A
{
private:
float x[4];
float y[4];
public:
//Scaling functions, etc...
}
Class B
{
private:
float c[4];
public:
//Scaling functions etc...
}
What would be the best way to get x[4] passed to class B to put in c[4]? The real classes have much more going on, this is about as simple as I think I can make. x[4] has data that needs to be used in class B.
class A
{
private:
float x[4];
float y[4];
public:
float* getXs()
{
return x;
}
}
class B
{
private:
float c[4];
public:
//Scaling functions etc...
void setXs(float *x)
{
for (int i=0;i<4;i++)
c[i] = x[i];
}
}
Well, you could use friends, if you're not willing to write accessors:
http://en.wikipedia.org/wiki/Friend_class
Some would argue this breaks encapsulation, and that a getter would be the preferred approach.
Use a getter of x[4] on an instance of A when calling the constructor of B.
#include <string.h>
class A
{
private:
float x[4];
float y[4];
public:
float const *xArray() const
{
return x;
}
};
class B
{
private:
float c[4];
public:
void setCArray(float const arr[4])
{
memcpy(c, arr, 4 * sizeof(int));
}
};
int main()
{
A a;
B b;
b.setCArray(a.xArray());
}
There are number of ways. The best depends on Your criteria.
If time is not crucial for you I would be simple and use copy constructor:
Class A
{
private:
float x[4];
float y[4];
public:
const float& X(int i) { return x[i]; }
}
Class B
{
private:
float c[4];
public:
B( const A& a ) {
for( k = 0; k < 4; k++ )
c[k] = a.X(k);
}
}
If time is crucial you can consider to use pointers copy. But be Very accurate with it:
Class A
{
private:
friend B;
float x[4];
float y[4];
public:
...
}
Class B
{
private:
const float* const c;
public:
B( const A& a ):c(a.x){}
// use c like c[4], but don't change it.
}

Declaring readonly variables on a C++ class or struct

I'm coming to C++ from C# and const-correctness is still new to me. In C# I could declare a property like this:
class Type
{
public readonly int x;
public Type(int y)
{
x = y;
}
}
This would ensure that x was only set during initialization. I would like to do something similar in C++. The best I can come up with though is:
class Type
{
private:
int _x;
public:
Type(int y) { _x = y; }
int get_x() { return _x; }
};
Is there a better way to do this? Even better: Can I do this with a struct? The type I have in mind is really just a collection of data, with no logic, so a struct would be better if I could guarantee that its values are set only during initialization.
There is a const modifier:
class Type
{
private:
const int _x;
int j;
public:
Type(int y):_x(y) { j = 5; }
int get_x() { return _x; }
// disable changing the object through assignment
Type& operator=(const Type&) = delete;
};
Note that you need to initialize constant in the constructor initialization list. Other variables you can also initialize in the constructor body.
About your second question, yes, you can do something like this:
struct Type
{
const int x;
const int y;
Type(int vx, int vy): x(vx), y(vy){}
// disable changing the object through assignment
Type& operator=(const Type&) = delete;
};
Rather than a collection of constants, you could have a constant collection. The property of being constant seems to pertain to your use case, not the data model itself. Like so:
struct extent { int width; int height; };
const extent e { 20, 30 };
It's possible to have specifically constant data members of a class, but then you need to write a constructor to initialize it:
struct Foo
{
const int x;
int & y;
int z;
Foo(int a, int & b) : x(a + b), y(b), z(b - a) { }
};
(The example also shows another type of data member that needs to be initialized: references.)
Of course, structs and classes are the same thing.
You can initialize class const members with constructor. If you need add some other logic in constructor, but in .cpp file not in .h, you can create a private method and call it in constructor.
File.h
class Example
{
private:
const int constantMember1;
const int constantMember2;
const int constantMember3;
void Init();
public:
Example(int a, int b) :constantMember1(a), constantMember2(b), constantMember3(a + b) {
//Initialization
Init();
};
};
File.cpp
void Init()
{
//Some Logic intialization
}
This is not exactly answering the question asked, but if you wanted to have the simplicity of directly accessing member variables in a struct without getters, but wanted to ensure that nobody could modify the values, you could do something like this:
#include <iostream>
using namespace std;
class TypeFriend;
struct Type
{
const int &x;
const int y;
Type (int vx, int vy):x (_x), y (vy), _x (vx)
{
}
private:
friend class TypeFriend;
int _x;
};
struct TypeFriend
{
TypeFriend (Type & t):_t (t)
{
}
void setX (int newX)
{
_t._x = newX;
}
private:
Type & _t;
};
int main ()
{
Type t (1, 2);
TypeFriend tf (t);
cout << t.x << "," << t.y << endl;
// t.x = 6; // error: assignment of read-only location ‘t.Type::x’
// cout<<t.x << ","<<t.y<<endl;
tf.setX (5);
cout << t.x << "," << t.y << endl;
return 0;
}
The result of running this is:
1,2
5,2
Type::x cannot be modified externally, so it is read-only, but via TypeFriend it can be changed. This can be useful if you wanted to expose a simple interface of direct member access for reading, but wanted to restrict how those members could be changed.

single constructor to create objects with different data types

How to use a single constructor only to create the following objects using C++:
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
class A should be having a single constructor to accomodate the creation of objects x, y and z. No change is allowed in the 3 lines specified above.
You cannot(rather should not!) have a single constructor to create all these objects.
You can have constructors which can take different parameters precisely for this reason.
The important question to be asked is:
What exactly are you trying to achieve? What is the need for this?
Perhaps you are trying to solve a problem in wrong way. If you can provide some detail We could help you better.
Yuck!!!!
Anyway, if I was forced to (for example if this, hypothetically speaking, were a homework problem) I would use some sort of variant:
class Variant {
public:
Variant();
Variant( int );
Variant( double );
Variant( const char * );
~Variant();
private:
union data { ... };
enum type { ... };
};
And then use that in my horrid single constructor, along with default arguments to allow empty construction.
A::A( Variant p1 = Variant(), Variant p2 = Variant(), Variant p3 = Variant() );
With c++11:
#include <iostream>
struct A
{
template<typename... Args> A(Args&&... x)
{
std::cout << "construct A\n";
}
};
int main()
{
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
return 0;
}
In C++03 you can use initialization funntion:
class A
{
public:
A(int x, const char* y, double z)
{
Init(x, y, z);
}
A(const char* y, int x)
{
Init(x, y);
}
A()
{
Init();
}
private:
void Init(int x = 0, const char* y = 0, double z = 0)
{
}
};
In C++11 you can use constructor delegation:
class A
{
public:
A(int x, const char* y, double z)
{
}
A(const char* y, int x)
: A(x, y, 0)
{
}
A()
: A(0, 0, 0)
{
}
};
Why not just:?
class A {
public:
A(...) { }
};
// test:
int main() {
A x;
A y("Hello", 7);
A z(3, "Hello", 2.4);
}

How to access members by both name and as an array?

I have a bunch of vector classes. I have a 2D point vec2_t, a 3D point vec3_t and a 4D point vec4_t (you often want these when you have do graphics; this is graphics code, but the question has a generic C++ flavour).
As it is now, I have vec2_t declaring two members x and y; vec3_t subclasses vec2_t and has a third member z; vec4_t subclasses vec3_t and adds a w member.
I have a lot of near-duplicate code for operator overloading computing things like distances, cross products, multiplication by a matrix and so on.
I've had a few bugs where things have been sliced when I've missed to declare an operator explicitly for the subclass and so on. And the duplication bugs me.
Additionally, I want to access these members as an array too; this would be useful for some OpenGL functions that have array parameters.
I imagine that perhaps with a vec_t<int dimensions> template I can make my vector classes without subclassing. However, this introduces two problems:
How do you have a variable number of members that are also array entries, and ensure they align? I don't want to lose my named members; vec.x is far nicer than vec.d[0] or whatever imo and I'd like to keep it if possible
How do you have lots of the more expensive methods in a CPP source file instead of the header file when you take the templating route?
One approach is this:
struct vec_t {
float data[3];
float& x;
float& y;
float& z;
vec_t(): x(data[0]), y(data[1]), z(data[2]) {}
};
Here, it correctly aliases the array members with names, but the compiler I've tested with (GCC) doesn't seem to work out they are just aliases and so the class size is rather large (for something I might have an array of, and want to pass e.g. as a VBO; so size is a big deal) and how would you template-parameterise it so only the vec4_t had a w member?)
A possible solution (I think).
main.cpp:
#include <iostream>
#include "extern.h"
template <int S>
struct vec_t_impl
{
int values[S];
bool operator>(const vec_t_impl<S>& a_v) const
{
return array_greater_than(values, a_v.values, S);
}
void print() { print_array(values, S); }
virtual ~vec_t_impl() {}
};
struct vec_t2 : vec_t_impl<2>
{
vec_t2() : x(values[0]), y(values[1]) {}
int& x;
int& y;
};
struct vec_t3 : vec_t_impl<3>
{
vec_t3() : x(values[0]), y(values[1]), z(values[2]) {}
int& x;
int& y;
int& z;
};
int main(int a_argc, char** a_argv)
{
vec_t3 a;
a.x = 5;
a.y = 7;
a.z = 20;
vec_t3 b;
b.x = 5;
b.y = 7;
b.z = 15;
a.print();
b.print();
cout << (a > b) << "\n";
return 0;
}
extern.h:
extern bool array_greater_than(const int* a1, const int* a2, const size_t size);
extern void print_array(const int* a1, const size_t size);
extern.cpp:
#include <iostream>
bool array_greater_than(const int* a1, const int* a2, const size_t size)
{
for (size_t i = 0; i < size; i++)
{
if (*(a1 + i) > *(a2 + i))
{
return true;
}
}
return false;
}
void print_array(const int* a1, const size_t size)
{
for (size_t i = 0; i < size; i++)
{
if (i > 0) cout << ", ";
std::cout << *(a1 + i);
}
std::cout << '\n';
}
EDIT:
In an attempt to address the size issue you could change the member reference variables to member functions that return a reference.
struct vec_t2 : vec_t_impl<2>
{
int& x() { return values[0]; }
int& y() { return values[1]; }
};
Downside to this is slightly odd code:
vec_t2 a;
a.x() = 5;
a.y() = 7;
Note: Updated and improved the code a lot.
The following code uses a macro to keep the code clean and partial specialization to provide the members. It relies heavily on inheritence, but that makes it very easy to extend it to arbitary dimensions. It's also intended to be as generic as possible, that's why the underlying type is a template parameter:
// forward declaration, needed for the partial specializations
template<unsigned, class> class vec;
namespace vec_detail{
// actual implementation of the member functions and by_name type
// partial specializations do all the dirty work
template<class Underlying, unsigned Dim, unsigned ActualDim = Dim>
struct by_name_impl;
// ultimate base for convenience
// this allows the macro to work generically
template<class Underlying, unsigned Dim>
struct by_name_impl<Underlying, 0, Dim>
{ struct by_name_type{}; };
// clean code after the macro
// only need to change this if the implementation changes
#define GENERATE_BY_NAME(MEMBER, CUR_DIM) \
template<class Underlying, unsigned Dim> \
struct by_name_impl<Underlying, CUR_DIM, Dim> \
: public by_name_impl<Underlying, CUR_DIM - 1, Dim> \
{ \
private: \
typedef vec<Dim, Underlying> vec_type; \
typedef vec_type& vec_ref; \
typedef vec_type const& vec_cref; \
typedef by_name_impl<Underlying, CUR_DIM - 1, Dim> base; \
protected: \
struct by_name_type : base::by_name_type { Underlying MEMBER; }; \
\
public: \
Underlying& MEMBER(){ \
return static_cast<vec_ref>(*this).member.by_name.MEMBER; \
} \
Underlying const& MEMBER() const{ \
return static_cast<vec_cref>(*this).member.by_name.MEMBER; \
} \
}
GENERATE_BY_NAME(x, 1);
GENERATE_BY_NAME(y, 2);
GENERATE_BY_NAME(z, 3);
GENERATE_BY_NAME(w, 4);
// we don't want no pollution
#undef GENERATE_BY_NAME
} // vec_detail::
template<unsigned Dim, class Underlying = int>
class vec
: public vec_detail::by_name_impl<Underlying, Dim>
{
public:
typedef Underlying underlying_type;
underlying_type& operator[](int idx){
return member.as_array[idx];
}
underlying_type const& operator[](int idx) const{
return member.as_array[idx];
}
private:
typedef vec_detail::by_name_impl<Underlying, Dim> base;
friend struct vec_detail::by_name_impl<Underlying, Dim>;
typedef typename base::by_name_type by_name_type;
union{
by_name_type by_name;
underlying_type as_array[Dim];
} member;
};
Usage:
#include <iostream>
int main(){
typedef vec<4, int> vec4i;
// If this assert triggers, switch to a better compiler
static_assert(sizeof(vec4i) == sizeof(int) * 4, "Crappy compiler!");
vec4i f;
f.w() = 5;
std::cout << f[3] << '\n';
}
Of course you can make the union public, if you want to, but I think accessing the members through the function is better.
Note: The above code compiles cleanly without any warnings on MSVC10, GCC 4.4.5 and Clang 3.1 with -Wall -Wextra (/W4 for MSVC) and -std=c++0x (only for static_assert).
This would be one way to do it:
#include<cstdio>
class vec2_t{
public:
float x, y;
float& operator[](int idx){ return *(&x + idx); }
};
class vec3_t : public vec2_t{
public:
float z;
};
Edit: #aix is right in saying that it's non-standard and could cause problems. Perhaps a more appropriate solution would then be:
class vec3_t{
public:
float x, y, z;
float& operator[](int idx){
static vec3_t v;
static int offsets[] = {
((char*) &(v.x)) - ((char*)&v),
((char*) &(v.y)) - ((char*)&v),
((char*) &(v.z)) - ((char*)&v)};
return *( (float*) ((char*)this+offsets[idx]));
}
};
Edit #2: I have an alternative, where it's possible to only write your operators once, and not end up with a bigger class, like so:
#include <cstdio>
#include <cmath>
template<int k>
struct vec{
};
template<int k>
float abs(vec<k> const&v){
float a = 0;
for (int i=0;i<k;i++)
a += v[i]*v[i];
return sqrt(a);
}
template<int u>
vec<u> operator+(vec<u> const&a, vec<u> const&b){
vec<u> result = a;
result += b;
return result;
}
template<int u>
vec<u>& operator+=(vec<u> &a, vec<u> const&b){
for (int i=0;i<u;i++)
a[i] = a[i] + b[i];
return a;
}
template<int u>
vec<u> operator-(vec<u> const&a, vec<u> const&b){
vec<u> result;
for (int i=0;i<u;i++)
result[i] = a[i] - b[i];
return result;
}
template<>
struct vec<2>{
float x;
float y;
vec(float x=0, float y=0):x(x), y(y){}
float& operator[](int idx){
return idx?y:x;
}
float operator[](int idx) const{
return idx?y:x;
}
};
template<>
struct vec<3>{
float x;
float y;
float z;
vec(float x=0, float y=0,float z=0):x(x), y(y),z(z){}
float& operator[](int idx){
return (idx==2)?z:(idx==1)?y:x;
}
float operator[](int idx) const{
return (idx==2)?z:(idx==1)?y:x;
}
};
There are some problems, though:
1) I don't know how you'd go around defining member functions without having to write them (or at least some sort of stub) more than once.
2) It relies on compiler optimizations. I looked at the output from g++ -O3 -S and it seems that the loop gets unrolled and the ?:s get replaced with the proper field accesses. The question is, would this still be handled properly in a real context, say within an algorithm?
A simple solution might be the best here:
struct Type
{
enum { x, y };
int values[2];
};
Type t;
if (t.values[0] == t.values[Type::x])
cout << "Good";
You can also do something like this:
struct Type
{
int values[2];
int x() const {
return values[0];
}
void x(int i) {
values[0] = i;
}
};
If you do not want to write it yourself, you may check some of the libraries suggested on:
C++ Vector Math and OpenGL compatable
If you use one specific compiler, you may use non standard methods, like packing information or nameless structs (Visual Studio):
union Vec3
{
struct {double x, y, z;};
double v[3];
};
On the other hand, casting several member variables to an array seems dangerous because the compiler may change the class layout.
So the logic solution seems to have one array and using methods to access that array. For example:
template<size_t D>
class Vec
{
private:
float data[D];
public: // Constants
static const size_t num_coords = D;
public: // Coordinate Accessors
float& x() { return data[0]; }
const float& x() const { return data[0]; }
float& y() { static_assert(D>1, "Invalid y()"); return data[1]; }
const float& y() const { static_assert(D>1, "Invalid y()"); return data[1]; }
float& z() { static_assert(D>2, "Invalid z()"); return data[2]; }
const float& z() const { static_assert(D>2, "Invalid z()"); return data[2]; }
public: // Vector accessors
float& operator[](size_t index) {return data[index];}
const float& operator[](size_t index) const {return data[index];}
public: // Constructor
Vec() {
memset(data, 0, sizeof(data));
}
public: // Explicit conversion
template<size_t D2>
explicit Vec(const Vec<D2> &other) {
memset(data, 0, sizeof(data));
memcpy(data, other.data, std::min(D, D2));
}
};
Using the above class, you may access the member array using the [] operator, coordinates using the accessor methods x(), y(), z(). Slicing is prevented using explicit conversion constructors. It disables the use of the accessors for lower dimensions using static_assert. If you are not using C++11, you may use Boost.StaticAssert
You can also templatized your methods. You can use for in order to extend them to N dimensions or use recursive calls. For example, in order to compute the square sum:
template<size_t D>
struct Detail
{
template<size_t C>
static float sqr_sum(const Vec<D> &v) {
return v[C]*v[C] + sqr_sum<C-1>(v);
}
template<>
static float sqr_sum<0>(const Vec<D> &v) {
return v[0]*v[0];
}
};
template<size_t D>
float sqr_sum(const Vec<D> &v) {
return Detail<D>::sqr_sum<D-1>(v);
}
The above code can be used:
int main()
{
Vec<3> a;
a.x() = 2;
a.y() = 3;
std::cout << a[0] << " " << a[1] << std::endl;
std::cout << sqr_sum(a) << std::endl;;
return 0;
}
In order to prevent template bloat, you may code your templated methods on a cpp and instantiated them for D=1, 2, 3, 4.
This is yet another approach. The following works on gcc C++11:
#include <stdio.h>
struct Vec4
{
union
{
float raw[4];
struct {
float x;
float y;
float z;
float w;
};
};
};
int main()
{
Vec4 v = { 1.f, 2.f, 3.f, 4.f };
printf("%.2f, %.2f, %.2f, %.2f\n", v.x, v.y, v.z, v.w);
printf("%.2f, %.2f, %.2f, %.2f\n", v.raw[0], v.raw[1], v.raw[2], v.raw[3]);
return 0;
}

"Retroactive Union" - can it be done?

I've got two classes: a template class, and a regular class that inherits from it:
template <int N> class Vector
{
float data[N];
//etc. (math, mostly)
};
class Vector3 : public Vector<3>
{
//Vector3-specific stuff, like the cross product
};
Now, I'd like to have x/y/z member variables in the child class (full members, not just getters - I want to be able to set them as well). But to make sure that all the (inherited) math works out, x would have to refer to the same memory as data[0], y to data[1], etc. Essentially, I want a union, but I can't declare one in the base class because I don't know the number of floats in the vector at that point.
So - can this be done? Is there some sort of preprocessor / typedef / template magic that will achieve what I'm looking for?
PS: I'm using g++ 4.6.0 with -std=c++0x, if that helps.
Edit: While references would give the syntax I'm looking for, the ideal solution wouldn't make the class any bigger (And references do - a lot! A Vector<3> is 12 bytes. A Vector3 with references is 40!).
How about:
class Vector3 : public Vector<3>
{
public:
// initialize the references...
Vector3() : x(data[0]), y(data[1]), z(data[2]){}
private:
float& x;
float& y;
float& z;
};
Of course, if you want them to occupy the same space, then that's a different story...
With a little template magic, you can do the following...
#include <iostream>
template <int N, typename UnionType = void*> struct Vector
{
union
{
float data[N];
UnionType field;
};
void set(int i, float f)
{
data[i] = f;
}
// in here, now work with data
void print()
{
for(int i = 0; i < N; ++i)
std::cout << i << ":" << data[i] << std::endl;
}
};
// Define a structure of three floats
struct Float3
{
float x;
float y;
float z;
};
struct Vector3 : public Vector<3, Float3>
{
};
int main(void)
{
Vector<2> v1;
v1.set(0, 0.1);
v1.set(1, 0.2);
v1.print();
Vector3 v2;
v2.field.x = 0.2;
v2.field.y = 0.3;
v2.field.z = 0.4;
v2.print();
}
EDIT: Having read the comment, I realise what I posted before was really no different, so a slight tweak to the previous iteration to provide direct access to the field (which is what I guess you are after) - I guess the difference between this and Rob's solution below is that you don't need all the specializations to implement all the logic again and again...
How about template specialization?
template <int N> class Vector
{
public:
float data[N];
};
template <>
class Vector<1>
{
public:
union {
float data[1];
struct {
float x;
};
};
};
template <>
class Vector<2>
{
public:
union {
float data[2];
struct {
float x, y;
};
};
};
template <>
class Vector<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.x;
v3.data[1];
};
EDIT Okay, here is a different approach, but it introduces an extra identifier.
template <int N> class Data
{
public:
float data[N];
};
template <> class Data<3>
{
public:
union {
float data[3];
struct {
float x, y, z;
};
};
};
template <int N> class Vector
{
public:
Data<N> data;
float sum() { }
float average() {}
float mean() {}
};
class Vector3 : public Vector<3>
{
};
int main() {
Vector3 v3;
v3.data.x = 0; // Note the extra "data".
v3.data.y = v3.data.data[0];
};
Here's one possibility, cribbed from my answer to this question:
class Vector3 : public Vector<3>
{
public:
float &x, &y, &z;
Vector3() : x(data[0]), y(data[1]), z(data[2]) { }
};
This has some problems, like requiring you to define your own copy constructor, assignment operator etc.
You can make the following:
template <int N> struct Vector
{
float data[N];
//etc. (math, mostly)
};
struct Vector3_n : Vector<3>
{
//Vector3-specific stuff, like the cross product
};
struct Vector3_a
{
float x, y, z;
};
union Vector3
{
Vector3_n n;
Vector3_a a;
};
Now:
Vector3 v;
v.n.CrossWhatEver();
std::cout << v.a.x << v.a.y << v.a.z
You could try the anonymous union trick, but that is not standard nor very portable.
But note that with this kind of union it is just too easy to fall into undefined behaviour without even noticing. It will probably mostly work anyway, though.
I wrote a way a while back (that also allowed getters/setters), but it was such a non-portable garrish hack that YOU REALLY SHOULD NOT DO THIS. But, I thought I'd throw it out anyway. Basically, it uses a special type with 0 data for each member. Then, that type's member functions grab the this pointer, calculate the position of the parent Vector3, and then use the Vector3s members to access the data. This hack works more or less like a reference, but takes no additional memory, has no reseating issues, and I'm pretty sure this is undefined behavior, so it can cause nasal demons.
class Vector3 : public Vector<3>
{
public:
struct xwrap {
operator float() const;
float& operator=(float b);
float& operator=(const xwrap) {}
}x;
struct ywrap {
operator float() const;
float& operator=(float b);
float& operator=(const ywrap) {}
}y;
struct zwrap {
operator float() const;
float& operator=(float b);
float& operator=(const zwrap) {}
}z;
//Vector3-specific stuff, like the cross product
};
#define parent(member) \
(*reinterpret_cast<Vector3*>(size_t(this)-offsetof(Vector3,member)))
Vector3::xwrap::operator float() const {
return parent(x)[0];
}
float& Vector3::xwrap::operator=(float b) {
return parent(x)[0] = b;
}
Vector3::ywrap::operator float() const {
return parent(y)[1];
}
float& Vector3::ywrap::operator=(float b) {
return parent(y)[1] = b;
}
Vector3::zwrap::operator float() const {
return parent(z)[2];
}
float& Vector3::zwrap::operator=(float b) {
return parent(z)[2] = b;
}
To finish off an old question: No. It makes me sad, but you can't do it.
You can get close. Things like:
Vector3.x() = 42;
or
Vector3.x(42);
or
Vector3.n.x = 42;
or even
Vector3.x = 42; //At the expense of almost quadrupling the size of Vector3!
are within reach (see the other answers - they're all very good). But my ideal
Vector3.x = 42; //In only 12 bytes...
just isn't doable. Not if you want to inherit all your functions from the base class.
In the end, the code in question ended up getting tweaked quite a bit - it's now strictly 4-member vectors (x, y, z, w), uses SSE for vector math, and has multiple geometry classes (Point, Vector, Scale, etc.), so inheriting core functions is no longer an option for type-correctness reasons. So it goes.
Hope this saves someone else a few days of frustrated searching!