Lets say I have this class:
template <class T>
class Test
{
Test(T* x);
const T* const t;
int i{0};
};
I want t
to always be initialized with x
:
template <class T> Test<T>::Test(T* x) : t{x} {}
And I have two specializations:
template <> Test<Foo>::Test(Foo* x) : t{x} { i = 1; }
template <> Test<Bar>::Test(Bar* x) : t{x} { i = 2; }
Next, I'm extending the class with some other stuff, and that first (templated) constructor does a lot more than just setting t
. I want to do all those things for both T = Foo
and T = Bar
.
Is there some way that I can call the templated constructor from the specialized constructors?
// This does not work, since it will create a delegation cycle
template <> Test<Foo>::Test(Foo* x) : Test(x) { i = 1; }
template <> Test<Bar>::Test(Bar* x) : Test(x) { i = 2; }
You can use a delegating constructor for this.
You can create a private constructor, that takes the pointer for t
, and an int
for i
. Then you can use that to set x
and i
, and run all of the shared code.
That would look like:
template <class T>
class Test
{
public:
Test(T* x) : Test(x, 0) { /*code for default case, runs after delegate*/ }
private:
Test(T* t, int i) : t(t), i(i) { /*code to run for everything*/ }
const T* const t;
int i;
};
template <> Test<Foo>::Test(Foo* x) : Test(x, 1) { /*code only for Foo, runs after delegate*/ }
template <> Test<Bar>::Test(Bar* x) : Test(x, 2) { /*code only for Bar, runs after delegate*/ }
Can the delegate constructor be the generic/templated constructor (with the same signature as the specific, specialized constructors for Foo and Bar)?
No, that isn't possible. When you specialize a function template, you aren't creating a new function, but instead specifying that if T
gets deduced to the type you specify in the specialization, then use the specialization definition in place of the generic one.
That is why I have "all three constructors" (the generic and the two specializations) call Test(T* t, int i)
, which handles the code that is shared by all cases.