Reputation: 651
Suppose I want to write a class that represents an immutable normalized (norm == 1) vector in two dimensions along with a mutable int
:
#include <cmath>
#include <iostream>
double norm2d(double x, double y)
{
return sqrt(x*x + y*y);
}
class NormalizedVector {
public:
NormalizedVector(double x, double y, int some_int)
: m_x(x / norm2d(x, y)), m_y(y / norm2d(x, y)), m_some_int(some_int){};
void set_some(int i) { m_some_int = i; }
private:
const double m_x;
const double m_y;
int m_some_int;
friend std::ostream& operator<< (std::ostream& os, const NormalizedVector& v) {
return os << "(" << v.m_x << "," << v.m_y << ")" << " : " << v.m_some_int;
}
};
int
main() {
NormalizedVector v { 1, 1 , 42};
std::cout << v << std::endl;
v.set_some(23);
std::cout << v << std::endl;
return 0;
}
Is it in this situation possible to avoid calling norm2d(x, y)
twice in the ctor while still using initialization lists? Note that default-constructing members and assigning them in the ctor's body is not possible because the vector components are const
.
I am well aware that this MWE is not very realistic but in the past I have for several times stumbled upon a situation where one function (or "some code") was required to compute values for multiple members in the initialization list and where in-body-assigning them was not an option because the corresponding members where either const
or not zero-cost-default-constructable.
Upvotes: 2
Views: 60
Reputation: 62939
Yes, you can have a private constructor that takes an additional parameter, and delegate to that.
class NormalizedVector {
public:
NormalizedVector(double x, double y, int some_int)
: NormalizedVector(x, y, some_int, norm2d(x, y)) {};
void set_some(int i) { m_some_int = i; }
private:
NormalizedVector(double x, double y, int some_int, double norm)
: m_x(x / norm), m_y(y / norm), m_some_int(some_int){};
const double m_x;
const double m_y;
int m_some_int;
friend std::ostream& operator<< (std::ostream& os, const NormalizedVector& v) {
return os << "(" << v.m_x << "," << v.m_y << ")" << " : " << v.m_some_int;
}
};
Upvotes: 3