C++ основной вопрос о конструкторе

Как должен я обрабатывать следующую ситуацию:

Я пишу свой собственный 2D векторный класс и имею следующий код:

class Vector2 : public (...)
public:

   Vector2(float x, float y) {

      local_vector_storage_[0] = x;
      local_vector_storage_[1] = y;
   }

   template <typename Iterator> Vector2(Iterator begin, Iterator end) {

      ASSERT(end - begin == 2);

      resize(2);

      std::copy(begin, end, local_vector_storage_.begin());
   }

// ...
};

Теперь, если я говорю Vector2 v(3.0f, 4.0f); это компилирует прекрасный и вызывает соответствующего конструктора плавающего.

Но если я пишу Vector2 v(3, 4); это перестало работать, потому что шаблонный конструктор итератора "соответствует лучше" и Vector2(Iterator(3), Iterator(4)) назван.

Что я должен сделать в этом случае?

Моя идея была о представлении assign(It1, It2) членский метод вместо конструктора, но возможно существует лучшее решение?

Править:

Кроме того, о чем Вы думаете ASSERT(end - begin == 2) строка? Я знаю, что это означает, что я не могу, например, передать итераторы std::list, но приносит дополнительную безопасность. Я должен сделать это или нет?

8
задан Yippie-Ki-Yay 8 July 2010 в 15:38
поделиться

4 ответа

Что-то вроде этого, кажется, работает:

template<typename T>
struct notnumeric {typedef int OK;};

template<>
struct notnumeric<int> {};

class Vector2
{
public:
   Vector2(float x, float y)
   {
   }

   template <typename Iterator>
   Vector2(Iterator begin, Iterator end, typename notnumeric<Iterator>::OK dummy = 0)
   {
   }
};

Я полагаю, что здесь используется SFINAE, чтобы предотвратить выбор компилятором второго ctor для нечисловых типов.

Что касается ASSERT (end - begin == 2), я думаю, вам следует использовать std::distance(begin, end) для определения расстояния между двумя итераторами.

6
ответ дан 5 December 2019 в 18:56
поделиться
1
ответ дан 5 December 2019 в 18:56
поделиться

РЕДАКТИРОВАТЬ: Это 2-мерный вектор? Или всего два вектора? Я ответил на это для 2-мерного вектора.

Как мне поступить в следующей ситуации

Я думаю, вы должны справиться с ней, удалив конструктор float . Из чтения кода непонятно, какой объект от этого следует ожидать.

Читая код callite, у меня не было бы оснований полагать, что vector2 v2 (1, 5); создает вектор из двух векторов, каждый с одним значением.

Лично я ожидал, что он создаст матрицу 1x5 .

Если это типичный вариант использования вашей библиотеки, рассмотрите именованный конструктор :

vector2 Create2x1(float f1, float f2);

re: ASSERT

ASSERT - это хорошая проверка работоспособности, но требует вашего Iterator для поддержки произвольного доступа (или, по крайней мере, вычитания для определения расстояния). Это может чрезмерно ограничить его использование. Рассмотрите возможность использования std :: distance или проверки того, что local_vector_storage имеет второй размер.

1
ответ дан 5 December 2019 в 18:56
поделиться

В конкретном случае я вообще не вижу смысла вводить Vector2 (Iterator begin, Iterator end) c'tor.

В общем, я не вижу смысла имитировать std :: vector (который по сути является оболочкой для массива), когда размер вашего Vector2 фиксирован и никогда не меняется . Перекрытие вариантов использования между std :: vector и вашим Vector2 незначительно или отсутствует: std :: vector часто инициализируется из другого контейнера, тогда как Vector2 будет инициализирован 50/50 двумя значениями или другим Vector2.

И даже если вы решите продолжить, строка:

ASSERT(end - begin == 2);

резко ограничит полезность конструктора, поскольку относительно небольшое количество итераторов поддерживают арифметику.

1
ответ дан 5 December 2019 в 18:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: