我有一个特定的问题,即将支持的类型添加到现有的旧版std :: list操作函数中。我试图用模板做这个没有成功,所以我很欣赏任何关于如何更好地使用模板或完全使用不同机制的建议。请看下面我的情景,如果对此有任何想法,请告诉我。在此先感谢您的帮助!
我目前有两个类型为A的std :: list,并且为它们提供了insert / removal / getter / etc函数。有关此内容的简化代码段如下所示。
typedef std::list<A*> TListA;
TListA ListA1;
TListA ListA2;
void InsertIntoListA(A* pA)
{
TListA& ListA = IsBoo()? ListA1 : ListA2;
ListA.push_back(pA);
}
现在,事实证明我需要添加类型B,并且我考虑使用模板添加这种新类型(如下所示),但事实证明这有两个问题。
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);
}
问题1: 我不能拥有“std :: list&amp; List”,因为它是引用的,需要将它分配给一个实际的列表。所以我最终会得到类似的东西,这并不理想。
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);
}
}
问题2: 我得到A到B或B到A的类型转换错误。我认为这是因为给定模板T,编译器将枚举“ListA.push_back”和“ListB.push_back”的所有四种可能性,这导致将A插入列表A,将B插入列表A,将A插入列表B,然后将B插入列表B,其中只有两个有效。所以我最终得到了这样的东西,我认为这会破坏使用模板的目的。
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));
}
}
答案 0 :(得分:1)
不要将所有功能混合在一起。这是非常糟糕的做法。使用像
这样的东西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);
}
或某些特征,或其他东西。但无论如何,一个函数中的条件并不多。
为什么不将实际列表传递给插入函数?会更好。
答案 1 :(得分:1)
显然,你不能在函数模板中进行列表类型切换,因为每个模板实例化只能识别这两种类型中的一种。所以你必须在功能之外进行切换。这是一种可能性:
TListA& getList(bool isBoo, A* /*dummy*/)
{
return isBoo ? ListA1 : ListA2;
}
TListB& getList(bool isBoo, B* /*dummy*/)
{
return isBoo ? ListB1 : ListB2;
}
template <typename T>
void InsertIntoListT(T* pT)
{
auto& theList = getList(IsBoo(), (T*)NULL);
theList.push_back(pT);
}
虚拟物仅用于类型siwtching - 可以通过功能模板和专业化来完成,但这很难看。根据List变量的真实性质,getList
功能可以通过其他方式编写。也许更通用,也许不是。