1

我是 C++ 模板编程的新手。

我想要做的是为其项目的某个属性编写一个具有固定容量的通用容器。

template <typename T >
    class SinkContainer{

    std::list<T> _buffer;

    int sum(); // i don't know how to implement this :-(
    public:
    void push_back(T a);
}

类型T可以是

Class Client{
    public:
    int num_of_accounts;
}

或者

class Supplier{
public:
     int num_of_warehouse
}

容器只能包含一个MAX_NUM帐户或仓库,这意味着每次我们插入缓冲区时,我们都需要总结当前总帐户或仓库数量。

任何人都可以建议一种编写这个通用容器的方法吗?我应该覆盖 + for ClientandSupplier吗?

4

5 回答 5

3

这通常使用所谓的特征类来解决。基本上,您定义一个适配器,它为您的模板提供统一的接口供您使用。

// Traits class definition
template <class T>
struct SinkSumTraits;

template <>
struct SinkSumTraits<Client>
{
    static int summand(const Client &c) { return c.num_of_accounts; }
};

template <>
struct SinkSumTraits<Supplier>
{
    static int summand(const Supplier &s) { return s.num_of_warehouse; }
};


// Traits class usage

template <typename T >
class SinkContainer {
    std::list<T> _buffer;

    int sum()
    {
        return std::accumulate(
            _buffer.begin()
            , _buffer.end()
            , 0
            , [](int s, const T &a) { return s + SinkSumTraits<T>::summand(a); }
        );
    }
public:
    void push_back(T a);
}

注意:如果您没有 C++11(对于 lambda 中使用的 lambda sum()),只需将其替换为SinkSumTraits<T>::summand().

于 2013-09-11T08:42:36.597 回答
2

在类 Client 和 Supplier 中编写一个“Getter”方法来获取它们的 number 属性。

这样您就可以随时调用方法并求和

int sum(void){
int iSum = 0;
for(std::list<T>::iterator it = _buffer.begin();it!=_buffer.end();++it){
    iSum+=it->GetNum();
}
return iSum;    
}
于 2013-09-11T08:41:12.263 回答
2

“具有固定容量的通用容器”是对std::array(或boost::array,取决于您可以使用的,如果有的话)的描述。至于通用求和,我不确定这个操作是否应该是容器的一部分。我相信使用泛型函数处理由迭代器对指定的任意 STL 样式序列、由迭代器分派的value_type方法是一种更清洁的解决方案。或者,更好的是,使用std::for_each. 类似的东西

int extract_number(const Client& c)
{
    return c.num_of_accounts;
}

int extract_number(const Supplier& s)
{
    return s.num_of_wareouse;
}

template <typename Iter>
int sumStuff(Iter begin, Iter end)
{
    typedef typename Iter::value_type type;
    int sum;
    std::for_each(begin, end, [&sum](const type& item)
    {
        sum += extract_number(item);
    }
    return sum;
}

这样,操作和容器就解耦了,我们得到了一个简洁的、参数多态的 sum 函数。

于 2013-09-11T08:44:40.083 回答
0

如果您无法修改客户和供应商 - 您可以使用模板专业化来实现您想要的:

template <typename T >
class SinkContainer{

     int getCount(T t);

}

.cpp 内部:

template<>
int SinkContainer<Client>::getCount(T t)
{
     return t.num_of_accounts;
}


template<>
int SinkContainer<Supplier>::getCount(T t)
{
     return t.num_of_warehouse;
}
于 2013-09-11T08:46:47.617 回答
0

好吧,您可以使用指向成员的指针,如下所示:

template <typename T, int T::*N>
class SinkContainer {
    bool do_push_back(T const &);
public:
    int sum();
    bool push_back(T const &t) {
        if (sum() + t.*N < MAX_NUM)
            return do_push_back(t);
        else
            return false;
    }
};

并将其用作

SinkContainer<Client, &Client::num_of_accounts> clients;
SinkContainer<Supplier, &Supplier::num_of_warehouse> suppliers;

但它非常不灵活。计数器必须是整数数据成员(它不能是无符号的、长的或动态计算的),并且 MAX_NUM 是硬编码的。

特征方法为您提供了更大的灵活性,因为它可以为每种类型做不同的事情:Agnew 已经展示了这一点,所以我不会重复它。

于 2013-09-11T08:51:51.903 回答