Каков наилучший способ использовать общий тип векторного размера? - PullRequest
1 голос
/ 11 января 2012

При создании шаблонного векторного класса, как лучше всего разрешить использовать его тип размера? Из того, что я собрал, кажется, что нужно создать интерфейс для реального векторного класса, а затем использовать его. Такие как

for(VectorBase::size_type i = 0; i < test1.size(); ++i)

Это имеет преимущество перед

for(Vector<int>::size_type i = 0; i < test1.size(); ++i)

для того, чтобы сделать код чище и не знать шаблонный тип вектора (в случае его изменения).

Для примера моей реализации (если есть лучший способ, вот как я его создал).

class VectorBase
{
public:
    typedef unsigned int size_type;

protected:
    size_type mCount;

public:
    VectorBase() { mCount = 2; } 
    virtual ~VectorBase() = 0 { }
    size_type size() const { return mCount; }
};

template<typename Type>
class Vector : public VectorBase
{
public:
    Vector() : VectorBase() { }
    ~Vector() { }
};

int main(void)
{
    Vector<int> test1;

    for(VectorBase::size_type i = 0; i < test1.size(); ++i)
    {
        cout << i << endl;
    }

    system("PAUSE");

    return(0);
}

(Примечание: пожалуйста, не превращайте это в «Просто используйте векторный класс xxx.»).

Ответы [ 3 ]

1 голос
/ 11 января 2012

Я не думаю, что есть лучший способ. : -)

Перемещая некоторые части в общий базовый класс, вы упрощаете интерфейс, но вы также отбираете некоторые варианты для производных классов или специализаций вашего шаблона.

Например, vector<char> может потребоваться тип размера long long, если вы хотите, чтобы он содержал очень большое количество символов. Потенциальная специализация для vector<my_huge_type>, возможно, нуждается только в int?

Должны ли мы заранее решить, что unsigned int всегда достаточно хорош? Может быть, а может и нет. Разработка интерфейса, если часто приходится находить хороший баланс между сложностью и гибкостью.

1 голос
/ 11 января 2012

не нужно знать шаблонный тип вектора (в случае его изменения).

Если вас беспокоит изменение типа контейнера, либо:

  1. Создайте для него typedef, поэтому test1 объявляется с использованием того же имени типа, которое вы используете в цикле, но тип, представленный этим именем, может измениться в будущем.
  2. Напишите правильные обобщенные функции,тип контейнера - это параметр шаблона T или любой другой, и вы используете typename T::size_type в качестве типа i.Тогда, если тип меняется, ваш код справляется.

Пример (1):

typedef vector<int> test_type;
test_type test1;
// populate the vector
for (test_type::size_type i = 0; i < test1.size(); ++i) std::cout << i << '\n';

Пример (2):

template <typename Container>
void print_indexes(const Container &test1) {
    for (typename Container::size_type i = 0; i < test.size(); ++i) {
        std::cout << i << '\n';
    }
}

Альтернативаобходные пути:

1) Просто используйте std::size_t.Немного обмана, так как в принципе я предполагаю, что vector<bool> может иметь больше чем SIZE_MAX элементов, но ни один "правильный" вектор не может быть больше этого.

2) (только C ++ 11) use auto как тип i

for (auto i = test.size(); i != 0; --i) std::cout << (test.size() - i) << '\n';

или

for (decltype(test.size()) i = 0; i < test1.size(); ++i) ...

Лично я бы следовал стилю, используемому в стандартных библиотеках, и не беспокоился об общем базовом классе дляшаблон класса контейнера.

0 голосов
/ 11 января 2012

Почему вы хотите переписать Vector, если он уже есть?

Если вам все же пришлось наследовать от VectorBase, хотя было бы лучше предоставить VectorBase защищенный деструктор, а не общедоступный виртуальный, как теперь вы дали Vector v-таблицу.

Кстати, синтаксис вашего чистого виртуального деструктора не является стандартным.

Нет никаких накладных расходов компилятора (т. Е. Раздувания) в сохранении typedef для size_type в каждом векторном шаблоне, поэтому не было бы большого преимущества в его перемещении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...