I have a specific question about adding supported types to existing legacy std::list manipulation functions. I tried to do this with templates without success, so I'd appreciate any advice on how to use templates better or use different mechanisms entirely. Please take a look at my scenario below and let me know if there's any thoughts on this. Thanks in advance for any help!
I currently have two std::lists of type A, and have insertion/removal/getter/etc functions for them. A simplified code snippet for this is shown below.
typedef std::list<A*> TListA;
TListA ListA1;
TListA ListA2;
void InsertIntoListA(A* pA)
{
TListA& ListA = IsBoo()? ListA1 : ListA2;
ListA.push_back(pA);
}
Now, it turns out I need to add type B, and I considered using templates to add this new type (as shown below), but it turns out there are two issues with that.
template <typename T>
void InsertIntoListT(T* pT)
{
std::list<T*>& List;
if (IsA())
List = IsBoo()? ListA1 : ListA2;
else
List = IsBoo()? ListB1 : ListB2;
List.push_back(pT);
}
Issue 1: I cannot have "std::list& List" because since it's by reference, it needs to be assigned to an actual list. So I would end up with something like this, which is not ideal.
template <typename T>
void InsertIntoListT(T* pT)
{
if (IsA()) {
TListA& ListA = IsBoo()? ListA1 : ListA2;
ListA.push_back(pT);
} else {
TListB& ListB = IsBoo()? ListB1 : ListB2;
ListB.push_back(pT);
}
}
Issue 2: I am getting type conversion errors with either A to B, or B to A. I think this is because given the template T, the compiler will enumerate all four possibilities for "ListA.push_back" and "ListB.push_back," which leads to inserting A to list A, inserting B to list A, inserting A to list B, and inserting B to list B, and only two of these are valid. So I end up with something like this, which I think defeats the purpose of using templates.
template <typename T>
void InsertIntoListT(T* pT)
{
if (IsA()) {
TListA& ListA = IsBoo()? ListA1 : ListA2;
ListA.push_back(reinterpret_cast<A*>(pT));
} else {
TListB& ListB = IsBoo()? ListB1 : ListB2;
ListB.push_back(reinterpret_cast<B*>(pT));
}
}
Don't mix all in one function. It's very bad practice. Use something like
void InsertIntoListImpl(A* p)
{
(IsBoo() ? ListA1 : ListA2).push_back(p);
}
void InsertIntoListImpl(B* p)
{
(IsBoo() ? ListB1 : ListB2).push_back(p);
}
template<typename T>
void InsertIntoList(T* p)
{
InsertIntoListImpl(p);
}
or some traits, or something else. But anyway, not many conditions in one function.
Any why not pass actual list to function for insert? It will be better.