Изменение размера локальных контейнеров в методе const через базовый класс с использованием специализаций шаблонов - PullRequest
2 голосов
/ 02 ноября 2019

Я хочу создать экземпляры класса и, в зависимости от типа, предоставить функцию изменения размера, которая применима только к контейнерам, которые предоставляют такую ​​функцию (для простоты, давайте предположим, что это просто вектор). Изменение размера выполняется в базовом классе, так как у меня есть несколько классов, которые имеют общую базу, но все требуют одинаковой функциональности.

Следующий код демонстрирует текущую проблему

#include <iostream>
#include <vector>

class base {
  public:
    template<typename T>
    void resize(T &var, T &resizer) {
      var.resize(resizer.size());
      std::cout << "resized a vector" << std::endl;
    }

    void resize(double &var, double &resizer) {
      std::cout << "just a double, no resizing done" << std::endl;
    }
};

template<typename T>
class child1 : public base {
  public:
    void doOperation() const {
      T a, b;
      // assume here that b has actually a different size from a
      this->resize(a, b);
    }
};

template<typename T>
class child2 : public base {
  public:
    void wildlyDifferentOperation() const {
      T c, d;
      // assume here that d has actually a different size from c
      this->resize(c, d);
    }
};

int main() {
  child1<std::vector<double>> obj1;
  obj1.doOperation();

  child2<std::vector<int>> obj2;
  obj2.wildlyDifferentOperation();

  child1<double> obj3;
  obj3.doOperation();
  return 0;
}

Как показано здесьЯ использовал специализацию шаблонов для отлова типов, размер которых не может быть изменен (и я знаю, что он всегда будет двойным), и я использую шаблонную версию для контейнеров, размер которых можно изменить, так как я не знаю заранее, какие типы я на самом деленужно (т.е. это может быть std::vector<int>, std::vector<double> и т. д.).

Конечно, если я удаляю const из метода doOperation(), тогда код работает, как и ожидалось, но с константойЯ получаю сообщение об ошибке error: passing ‘const child1<std::vector<double> >’ as ‘this’ argument discards qualifiers [-fpermissive], что неудивительно (и я получаю похожее сообщение для child2 и wildlyDifferentOperation()).

Теперь у меня вопрос: как я могу использовать приведенный выше код, чтобы он работал? Хотя я мог const_cast аргументы в this->resize или использовать mutable, а затем объявить T a в качестве переменных-членов класса, но безрезультатно. Любые предложения приветствуются, но я бы хотел, чтобы следующее не изменилось:

  1. void doOperation() и wildlyDifferentOperation() должны остаться const
  2. Я хочу иметь возможность создавать локальныепеременные как T a внутри doOperation() и wildlyDifferentOperation() и передают их в отдельный метод, где они изменяют размер, если они являются контейнером. Чтобы упростить ситуацию, я знаю, что я получу double или контейнер, но я не хочу налагать какие-либо ограничения на аргументы шаблона контейнера (т. Е. Принимать std :: vector, std :: vector ии так далее)
  3. Мне нужно иметь возможность использовать ту же функциональность для изменения размеров моих контейнеров из других дочерних классов, производных от базового класса.

Если есть более чистое решение, нетребующие шаблонных специализаций, которые также были бы приемлемы. Однако он должен работать с компилятором, соответствующим C ++ 14.

1 Ответ

1 голос
/ 02 ноября 2019

Сделать base::resize или static или const. Не зная семантики того, что вы собираетесь здесь, я бы предположил const.

...