jeudi 26 mars 2015

Template meta-code and private members

I would like to do something like this:



template <typename T>
class Foo
{
...
public:
void DoSomething()
{
compile_time_if (T is ClassA)
{
m_T.DoThingOne();
m_T.DoThingTwo();
}
DoSomeFooPrivateThing();
m_T.DoThingThree();
}
T m_T;
};


In this case I know that all valid T implement DoThingThree, but only ClassA implements DoThingOne and DoThingTwo. This is not a duck-typing thing, I do want to only do this extra part for ClassA and I do not want to add these methods to the other possible Ts. I can't do casting, because the possible Ts are not inherited types.


I know that I can use an external helper template to accommodate this:



template <typename T>
void Foo_DoSomething(T& t)
{
t.DoThingThree();
}

template <>
void Foo_DoSomething(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
t.DoThingThree();
}

template <typename T>
class Foo
{
...
public:
void DoSomething()
{
Foo_DoSomething(m_T);
}
...
};


However now this external template doesn't have access to private members of Foo (can't call DoSomeFooPrivateThing), which limits its functionality, and it's exposed publicly to the outside, which isn't pretty. (Making the external method a friend just makes things worse.)


Another option is to implement it internally:



template <typename T>
class Foo
{
...
public:
void DoSomething()
{
DoSomethingImpl(m_T);
}
...
private:
template <typename T2>
void DoSomethingImpl(T2& t)
{
DoSomeFooPrivateThing();
t.DoThingThree();
}

template <>
void DoSomethingImpl(ClassA& t)
{
t.DoThingOne();
t.DoThingTwo();
DoSomeFooPrivateThing();
t.DoThingThree();
}
...
};


But this requires duplicating the outer template type and parameter. This is probably acceptable, but it still feels a bit odd.


Is there a better way to do this?


Aucun commentaire:

Enregistrer un commentaire