I have a class with const
members, and one constructor which calls another constructor with extra values filled in. Normally I could use a colon initializer for
You can add a parameters class and use either C++11 constructor delegation or a base class:
struct parameters {
int b; int c; int d;
parameters(int b): b(b), c(), d() {
myfunc(b, &c, &d);
}
};
// constructor delegation
class A {
public:
A(int b): A(parameters(b)) { }
A(parameters p): b(p.b), c(p.c), d(p.d) { }
};
// base/wrapper
class ABase {
ABase(parameters p): b(p.b), c(p.c), d(p.d) { }
};
class A: public ABase {
public:
A(int b): ABase(parameters(b)) { }
};
Where to put the results of myfunc
so it can be set and used from different mem-initializers? How about in a default argument?
class A
{
private:
struct InitData;
public:
A(int b, InitData data=InitData());
A(int b, int c, int d) : b(b), c(c), d(d) { };
const int b;
const int c;
const int d;
};
struct A::InitData
{
int setup(int b);
int c;
int d;
};
inline int A::InitData::setup(int b)
{
myfunc(b, &c, &d);
return b;
}
inline A::A(int b_, InitData data)
: b(data.setup(b_)),
c(data.c),
d(data.d) {}
A a(0);
Since the made up type is private and has no conversions, there's little risk of accidentally using it or abusing it.
How about making a helper function:
class A
{
static int initializor(int b) { int n; myfunc(b, &n); return n; }
public:
explicit A(int b_) : b(b_), c(initializor(b_)) { }
A(int b_, int c_) : b(b_), c(c_) { }
// ... as before ...
};
I prefer Kerrek SB's answer, but in your case there is the complication that you can't easily make separate initialisation functions for each member.
In that case, another solution is to move the members to a base class and initialize that base class with a helper class with non-const members. Your initialization code is moved to the helper class' constructors, and can assign without problems.
class A_init
{
public:
A_init(int b)
{
// do whatever you like with c and d:
c = ...;
d = ...;
}
int c; // Note: non-const
int d; // Note: non-const
};
class A_base
{
public:
A_base(int b, A_init init) : b(b), c(init.c), d(init.d) {}
A_base(int b, int c, int d) : b(b), c(c), d(d) {}
const int b;
const int c;
const int d;
};
class A : public A_base
{
public:
A(int b) : A_base(b, A_init(b)) {}
A(int b, int c, int d) : A_base(b, c, d) {}
};
If one wants restrict access to A_init
, one can switch to private and declare A
a friend.