I have a struct Cmplx which models complex numbers.
class Cmplx{
double x;
double y;
public:
Cmplx(int X, int Y){x = X; y = Y;}
double& operator->(...){...}
}
I need to implement the operator, such that
int main(){
Cmlpx z(1,2);
z->im = 5;
z->re = 2;
}
Changes my complex number into (2,5); I know how to do it when im and re are strings, but have no idea how to do it like this.
You might abuse of operator-> that way:
struct ComplexRef
{
ComplexRef* operator->() { return this;}
double& re;
double& im;
};
class Cmplx{
double x;
double y;
public:
Cmplx(int X, int Y){x = X; y = Y;}
ComplexRef operator->(){ return {x, y}; }
};
Demo
The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.
I have a class MyFloat:
class MyFloat
{
public:
float value = 0.0;
}
I use it so far in this way:
MyFloat *myfloat1 = new MyFloat;
myfloat1->value = 1.0;
How can I make
myfloat1 = 2.0;
if (myfloat1 < 3.0){
...
}
You can use operator= and operator float
class MyFloat
{
public:
float value = 0.0;
MyFloat& operator=(float f)
{
value = f;
return *this;
}
operator float() const
{
return value;
}
};
int main() {
MyFloat f;
f = 10.0f;
float x;
x = f;
return 0;
}
As others have mentiond you could provide a operator=(float), however for a MyFloat it is more natural to be constructed with a float instead of first constructing it and then assigning a value:
class MyFloat {
public:
float value = 0.0;
MyFloat(float x) : value(x) {}
MyFloat() {}
};
int main() {
MyFloat x;
x = 1.0; // works because MyFloat(float) is used
MyFloat y(2.0); // this is nicer
}
PS: as pointed out by R2RT, for x = 1.0; you dont want to use the constructor, but an assignment operator (I just left the line because thats what you were asking for). However, for a newly constructed MyFloat I would always prefer to pass the value to the constructor.
Your object is of type MyFloat, not float so you can't assign a float value to it. What you can do is assign a float value to a data member of your class by overriding the class' = assignment operator:
MyFloat& operator=(float p) {
value = p;
return *this;
}
I am interested in trying something where I create a custom type and then access to its members using dot semantics. For example:
Class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float x(){ return numbers[0]; }
float y(){ return numbers[1]; }
float z(){ return numbers[2]; }
}
So I can do something like this:
A a;
//do stuff to populate `numbers`
float x=a.x;
But I would also like to make the elements in numbers lvalues so I can do something like this:
A a;
a.y=5; //assigns 5 to numbers[1]
How can I do this setting method?
You can return a reference to allow assignment:
float & x(){ return numbers[0]; }
^
// usage
A a;
a.x() = 42;
You should also have a const overload, to allow read-only access to a const object:
float x() const {return numbers[0];}
^^^^^
// usage
A const a = something();
float x = a.x();
First. You made functions x, y and z but assigning them to float. This wouldn't work.
Second. Change these functions to return referencies:
class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float & x(){ return numbers[0]; }
float & y(){ return numbers[1]; }
float & z(){ return numbers[2]; }
};
...
A point;
float x = point.x();
point.x() = 42.0f;
There's another way: declare referencies as a members of class and initialize them in c-tor:
class A{ //simplified, omitting constructors and other methods
private:
float numbers[3];
public:
float & x;
float & y;
float & z;
A() : x( numbers[ 0 ] ), y( numbers[ 1 ] ), z( numbers[ 2 ] ) {}
};
...
A point;
float x = point.x;
point.x = 42.0f;
P.S. Pay an attention on comment, that gave #MikeSeymour
Not unless you actually have public variables named x, y and z.
Or you can return a reference and then do a.y() = 5
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;
}
So I have a vec4 class that uses members x,y,z,w which you can access using
point.x point.y etc.
However I want to reuse this vec4 class to be my color class (it already supports scalar multiplication, operator overloading lots of other nice stuff)
I just want to be able to refer to the members using another notation:
color.r
color.g
color.b
etc.
Is there anyway I can do this using a macro or other syntactic sugar?
If you are using Visual Studio (and are sure that it is the only target IDE...) you can use the following:
#include <cassert>
union vec4
{
struct
{
float x;
float y;
float z;
float w;
};
struct
{
float r;
float g;
float b;
float a;
};
};
int main()
{
vec4 vec = { 0 };
vec.y = 10.0f;
assert(vec.g == 10.0f);
return 0;
}
It will yield warnings warning C4201: nonstandard extension used : nameless struct/union, though you can disable it.
EDIT: as it turns out gcc supports this extension as well.
Unless you have a good amount of common behavior between a vector and a color I think this is a bad idea. But since you asked, here is a possible way to do that.
If you make the x, y, z and w members private and provide accessor methods to get to them, then it is easy to provide two alternative ways to refer to the same member variables. For example:
class vec4 {
private:
float _x, _y, _z, _w;
public:
// vector getter/setters
float& x() { return _x; }
float& y() { return _y; }
float& z() { return _z; }
float& w() { return _w; }
// color getter/setters
float& r() { return _x; }
float& g() { return _y; }
float& b() { return _z; }
float& a() { return _w; }
};
vec4 my_color;
my_color.r() = 1.0f;
my_color.g() = 0.0f;
my_color.b() = 0.0f;
my_color.a() = 1.0f;
You can easily do that with standalone accessor functions:
struct vec4 { double x, y, z; };
double& get_r(vec4& v) { return v.z; }
// and so on