If I have 2 constructor overloads
calculations(double vector, double angle);
calculations(double horizontalVector, double verticalVector);
How can I ensure the compiler specifically uses one of the overloads that I choose (as each of them do different things behind the scenes)?
If you want to have overloads, the types needs to be different. One way to do this is the so called whole value idiom.
Make a struct for each parameters: a vector (watching out for potential name clashes), angle and so on.
The you will have two different constructors.
Assuming that your parameters are actually polar and cartesian coordinates rather than vectors,
calculations(double length, double angle);
calculations(double x_coordinate, double y_coordinate);
you can abstract those into types,
struct Polar { double length, angle; };
struct Cartesian {double x, y; };
and overload
calculations(const Polar& p);
calculations(const Cartesian& c);
and then
calculations c1(Polar{1,1});
calculations c2(Cartesian{1,1});
To provide different functions with same parameters you can use tag dispatching, where you provide unused parameter to do overloading.
struct Calculations {
struct UseTwoVectors {};
Calculations(double vector, double angle);
Calculations(double horizontalVector, double verticalVector, const UseTwoVectors&);
};
int main() {
Calculations c(1, 2);
Calculations d(1, 2, Calculations::UseTwoVectors());
}
Overall I do not know what these arguments represent - I suspect there is something wrong with abstraction in your code. You could take a different approach and make a class from your parameters.
struct VectorAngle {
double vector, angle;
};
struct TwoVectors {
double horizontalVector, verticalVector;
};
struct Calculations {
Calculations(const VectorAngle& v);
Calculations(const TwoVectors& v);
};
int main() {
Calculations c(VectorAngle{1, 2});
Calculations d(TwoVectors{1, 2});
};
Related
I have to build an interface HistoWapper that aggregates a histogram class that has three methods which vary by their parameter count, which I have to call
class Histogram {
...
double Interpolate(double X);
double Interpolate(double X, double Y);
double Interpolate(double X, double Y, double Z);
...
};
Right now I'm doing a switch on the dimension of my histogram and selecting the correct implementation at runtime.
class HistoWrapper {
...
Histogram hist_;
int dimension;
double x_;
double y_;
double z_;
double getValue() {
if(dimension == 1)
return hist_.getValue(x_);
else if(dimension == 2)
return hist_.getValue(x_, y_);
else if(dimension == 3)
return hist_.getValue(x_, y_, z_);
}
...
};
This code has many problems. When the dimension is 1, y_ and z_ are unused variables which take up memory for nothing. And getValue() will be called for millions of values at runtime meaning the branching will be very expensive and inneficient with big data.
The dimension of the histogram is known at compile time.
I'm wondering how I could avoid to do this else if ? Perhaps C++17 constexpr could be used on the dimension with an int using non type template parameters ? Could variadic templates be a solution here too ?
If I'm given a struct variable like:
struct Quaternion {
float x;
float y;
float z;
float w;
}
But I need to call a function expecting a
struct Vector {
float x;
float y;
float z;
float w;
}
Is there a way in C++ to cast a variable of type Quaternion to type Vector?
You can write a converting constructor:
struct Quaternion {
float x;
float y;
float z;
float w;
explicit Quaternion(const Vector& vec) : x(vec.x),y(vec.y),z(vec.z),w(vec.w) {}
}
And similar for the other way.
In case you are looking for a way that does not require to copy the members, then I am not aware of a portable way to do that, and members having the same name does not help for that.
On the other hand, having same named members helps to write generic code like this:
template <typename T>
void foo(const T& t) {
std::cout << t.x << t.y << t.z << t.w;
}
You can call this with either a Quaternion or a Vector without needing to convert between them.
In case you cannot modify any existing code (not the structs nor the function you want to call), you can write a simple function to do the conversion (as suggested by ShadowRanger in a comment):
Vector Quat2Vect(const Quaternion& q) {
return {q.x,q.y,q.z,q.w};
}
If, as you said in a comment, you can't change to the two types, you could possibly "solve" the problem by using yet another type:
struct MyVector {
float x;
float y;
float z;
float w;
operator Quaternion() { return Quaternion{x, y, z, w}; }
operator Vector() { return Vector{x, y, z, w}; }
};
My advice: It's probably better to pick one or the other as the main type in your code and use a separate conversion function.
What I think you're hoping for, given that you specifically asked about "cast", is to use a cast to go from one to the other.
Vector v = {1, 2, 3, 4};
Quaternion* q = reinterpret_cast<Quaternion*>(&v);
do_something_with_quart(*q); // Could modify v if pass by reference
Strictly speaking, this is undefined behaviour, although it is overwhelmingly likely to work in practice, but I still wouldn't recommend it. If you're really desparate to do something cast like, it's legal to use memcpy so long as the member variables are the same type in the same order (and there are no virtual methods):
Vector v = {1, 2, 3, 4};
Quaternion q;
memcpy(&q, &v, sizeof(v));
do_something_with_quart(q);
memcpy(&v, &q, sizeof(v)); // Copy back any change
Although the language and documentation describes memcpy as a copying function, it has certain magical properties that often in practice make it identical to the previous block of code. But I would also strongly advise against this. I mean, yuck! Just look at it!!
This is just an addition to largest_prime_is_463035818's answer to point out that the members don't have to have the same name in order to write a generic function to use them. So long as there are an equal number of members, all are publicly accessible, and they have the same types, you can decompose objects with a structured-binding and use that.
template <typename T>
void foo(const T& t) {
auto const & [x, y, z, w] = t;
std::cout << x << y << z << w;
}
I've been playing around with C++ and I've noticed something that I don't quite understand:
typedef float degrees;
typedef float radians;
void my_func(degrees n);
void my_func(radians m);
Declaring a function like this, I get a warning that the function is re-declared as if they are identical. Does this mean, when looking at function definitions, the compiler only sees built-in types and doesn't care about custom defined types, and since they're bot floats, it just considers them to be the same function?...
If that's the case, how do I get around this? Do I just have to make a different function?
Another possibility is to define Radian and Degree classes to have an explicit conversion from floats and an implicit conversion to them.
class Radian{
float m_value;
public:
explicit Radian(float t_value) : m_value(t_value) { }
operator float() const { return m_value; }
};
class Degree{
float m_value;
public:
explicit Degree(float t_value) : m_value(t_value) { }
operator float() const { return m_value; }
};
void my_func(Radian r);
void my_func(Degree d);
my_func(Radian(10)); // calls the Radian overload
my_func(Degree(10)); // calls the Degree overload
my_func(10); // Doesn't call either because both ctors are explicit
The implicit conversions to float mean that you can pass a variable of type Radian or Degree to a function expecting float and it'll just work.
This version does mean that, unlike the typedefs, you won't be able to write things like
Degree alpha = 30;
Degree beta = 60;
Degree gamma = alpha + beta; // 90 degrees
However, if you want, you can also define arithmetic operators like operator+, operator*, etc for each class. For instance, you might want to always perform Degree arithmetic modulo 360, so that 180 + 180 = 0.
you can define classes to handle these problems. look this example:
class Degree{
public:
double angle;
Degree(){}
void my_func(){
// do some job
}
};
class Radian{
public:
double angle;
Radian(){}
void my_func(){
// do some job
}
};
int main(){
Degree deg;
Radian rad;
deg.my_func();
rad.my_func();
}
now they do different tasks in their functions.
OR if you don't want to make objects, you can make a static function in these classes.
class Radian{
public:
static void my_func(float radian){
// do some job
}
};
typedef float degrees;
typedef float radians;
int main(){
radians rad;
Radian::my_func(rad)
}
typedef only creates a new name for an already existing type, so the compiler associates degrees, radians and float as being the same data type, in your example. They are not custom types per say, rather just a new name for a pre-existing type.
The problem is that you are not using 2 different types but only 2 different alias to the same type, so for the compiler it's the same function.
Now the workaround are multiple:
The first one can be declare 2 different classes with only an attribute of type float, and if you want a implicit conversion to float of the double reimplement the conversion in this way:
class Radian{
public:
float angle;
Radian(){};
operator float() { return angle; }
};
Another solution can be declare 2 different functions name for example:
void my_func_deg(degrees n);
void my_func_rad(radians m);
or create 2 different classes with an internal function:
class Radian{
public:
double angle;
Radian(){};
void my_func();
};
I have a class which has a few large fields (say, some big matrices) and has member functions to compute these matrices (the actual number of the matrices is bigger, of course)
class MyClass {
protected:
MatrixType m_11, m_12;
public:
void compute_m_11(double x);
void compute_m_12(double x);
}
Now, the computation code is very similar, and the most complex part is correct indexing of the matrix elements (which is the same for all the matrices involved). So I was thinking about splitting the indexing and the computation into separate functions: a compute_matrix function which will perform the indexing and call a compute_element function for each set of indexes in the matrix. This would greatly improve code readability and ease debugging.
So the compute_matrix function would take a MatrixType reference to the class field which I need to fill in and a std::function which would perform the actual computation. I obviously want to avoid writing anything that will involve additional copying of the matrices, since they can be quite large.
So, the questions are:
Is it legal/efficient to pass a reference to a class field to a class member function?
If so, do I need to use std::bind to pass the computation member functions? The compute_elements functions need to access some other fields of MyClass.
This is what I have in mind:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, compute_elements_m12);};
}
It is legal (and not that uncommon) to pass a member reference, but your function type is wrong.
You could use std::bind, or you could use a plain pointer-to-member:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(MatrixType &m, double x, double (MyClass::*f) (int, int, double);
public:
void compute_m_11(double x) {compute_matrix(m_11, x, &MyClass::compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(m_12, x, &MyClass::compute_elements_m12);};
};
std::bind and std::function gives a more flexible implementation though.
Sure it's not uncommon to pass a class attribute to an internal member function and you can also use std:bind to call the member function, but the question is do you really need that or can you just use a simple "if" or something similar to decide what to use? I'd say it depends on how many choices your code path has to decide that better.
Why would you pass a reference to a class field to a class member function? A better solution would be to implement a get method and use that in the compute_matrix function. Your class will then look something like this:
class MyClass {
protected:
MatrixType m_11, m_12;
double compute_elements_m11(int i, int j, double x);
double compute_elements_m12(int i, int j, double x);
void compute_matrix(double x, std::function<double(int, int, double) > f);
public:
void compute_m_11(double x) {compute_matrix(x, compute_elements_m11);};
void compute_m_12(double x) {compute_matrix(x, compute_elements_m12);};
MatrixType& getMatrixType_11( return m_11 );
MatrixType& getMatrixType_12( return m_12 );
}
Is it worth to write classes representing 1D, 2D, 3D points using templates
template <class T>
class Point2D
{
protected:
T X, Y;
public:
Point2D(const T x, const T y) : hot smileyx), Y(y)) {}
...
};
template <class T>
class Point3D : public Point2D<T>
{
protected:
T Z;
public:
Point3D(const T x, const T y, const T z) : Point2D<T>(x,y), Z(z) {}
...
};
...or using this approach:
class Point2D
{
protected:
double X, Y;
public:
Point2D(const double x, const double y) : X(x), Y(y)) {}
...
};
class Point3D : public Point2D
{
protected:
double Z;
public:
Point3D(const double x, const double y, const double z) : Point2D(x,y), Z(z) {}
...
};
We understand the coordinates as continuous variables, so it makes sense to express them using double values. A similar situation arises when working with matrices. However in this case templates are widely used...
This class is not only for single use, but it will be part of the library... And my second part of the question. How some "measure" functions should be implemented?
template <class T>
T getDist(const Point2D <T> * p1, const Point2D<T> *p2)
{
....
}
or
double getDist(const Point2D <T> * p1, const Point2D<T> *p2)
{
....
}
Is it reasonable to write such function in general or for some specific type?
Why repeat yourself? Most of the content of those classes and functions will be the same.
Something like this works much better:
template <std::size_T N, typename T>
class Point
{
public:
Point()
{
std::fill_n(mData, N, T());
}
explicit Point(const T& pX) :
mData[0](pX)
{
// or some variant (enable_if also works)
static_assert(N == 1, "X constructor only usable in 1D");
}
explicit Point(const T& pX, const T& pY) :
mData[0](pX),
mData[1](pY),
{
static_assert(N == 2, "XY constructor only usable in 2D");
}
// incomplete, left as exercise for reader. :P
private:
T mData[N];
};
And you just use loops for the functions:
template <std::size_T N, typename T>
T getDist(const Point<N, T>& pFirst, const Point<N, T>& pSecond)
{
// generic, compiler will unroll loops
}
Based on my experience, I'd avoid like the plague creating a class hierarchy where a 3D point IS-A 2D point. It makes it far too easy for 3D points to unintentionally and silently be treated as 2D points. Better to keep coordinates of different dimensionality distinct types (as per GMan's answer) and require explicit coercion between types.
My current favourite implementation of this sort of thing is provided by Eigen. Even if it's license (LGPL) limits it's use to you, I'd suggest taking a look at it's elegantly templated vector and matrix types and learning from them.
It looks OK to me, provided that all functions are implemented correctly and efficiently. For distance measurement:
template <class T>
T getDist(const Point3D <T>& p1, const Point3D<T>& p2);
signature should be used. Distances can be in 3D also.
I've run into this situation, and had cause to allow different types for the X and Y values, where X was sometimes integral but Y always had higher precision (float or double depending on usage). Might be worth considering that upfront.
Some consideration should also be made on how the class will be used. You mentioned matrices. If you plan on solving systems using that class or anything else incolving matrix inversions (or other similar matrix operations) representing a matrix as a bunch of integers would be outlandish.
If you plan to use it as simply a table of sorts (or are only going to be adding/subtracting and multiplying the matrices) then you could template the class because a matrix full of integers would not provide weird (and incorrect) results for those operations.