0

我有一个关于将支持的类型添加到现有的传统 std::list 操作函数的具体问题。我试图用模板做到这一点但没有成功,所以我很感激任何关于如何更好地使用模板或完全使用不同机制的建议。请在下面查看我的场景,如果对此有任何想法,请告诉我。提前感谢您的帮助!

我目前有两个 A 类型的 std::lists,并为它们提供了插入/删除/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& 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));
    }     
}
4

2 回答 2

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);
}

dummy 仅用于类型 siwtching - 可以通过函数模板和专业化来完成,但这很难看。根据 List 变量的真实性质,getList可以通过其他方式编写功能。也许更通用,也许不是。

于 2013-01-28T07:45:06.820 回答
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);
}

或某些特征,或其他东西。但无论如何,一个函数中的条件并不多。

为什么不将实际列表传递给插入功能?会好起来的。

于 2013-01-28T07:39:30.173 回答