Вывод аргумента шаблона / шаблон переменной: как я могу заставить его работать? - PullRequest
0 голосов
/ 23 января 2019

У меня проблема с оборачиванием шаблонного класса в не шаблонный;

Я пытаюсь заставить этот код работать:

my_class.hpp

#ifndef MY_CLASS_HPP
#define MY_CLASS_HPP

#include <vector>
#include <iostream>

class VectorPrinter {

private:

  template<class value_type>
  static std::vector<value_type> vec;

public:

  template<class value_type>
  VectorPrinter(const std::vector<value_type>& vec_)
  {
    vec = vec_
    for (std::size_t i = 0; i<vec.size(); ++i)
      std::cout << vec[i] << std::endl;
  }

};

#endif /* MY_CLASS_HPP */

main.cpp

#include "my_class.hpp"
#include <string>

int main() {

std::vector<int> v1{1, 2, 3, 4, 5};
std::vector<std::string> v2{"Hello", "world", "!"};
std::vector<double> v3{2.5, 7.3, -5.1};

VectorPrinter vp1(v1);
VectorPrinter vp2(v2);
VectorPrinter vp3(v3);

return 0;

}

Я получаю следующее сообщение об ошибке при попытке компиляции (я пробовал -std = c ++ 11, -std = c ++ 14, -std = c ++17: без разницы, без разницы и при переключении с g ++ на clang):

./my_class.hpp:19:5: error: cannot refer to variable template 'vec' without a template argument list

Теперь: моя цель - обойти определение VectorPrinter как класса шаблона или, альтернативно, избегать указания аргумента шаблона в случае VectorPrinterне может быть не шаблонным;так что моя проблема находится в области вывода переменной шаблона или аргумента шаблона.

Это всего лишь тест для моего дипломного проекта;В конце концов мне нужно добиться возможности определить библиотеку шаблонов для ГСЧ и инкапсулировать эти классы в более сложные классы, которые выполняют прямое моделирование Монте-Карло.Итак, в конце я хотел бы что-то вроде:

template <class engineType>
class RngObject {
   // ...
};
class Ensemble {
   private:
      template<class engineType> RngObject<engineType> rng;
   // ...
};

Было бы довольно скучно определять каждый класс, который инкапсулирует ГСЧ в качестве шаблона;более того, меня просят избегать использования динамического полиморфизма времени, как минимум на этом этапе.

Я надеюсь, что кто-то может дать мне несколько полезных советов.Спасибо

Ответы [ 2 ]

0 голосов
/ 23 января 2019

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

Истинный шаблонный класс позволил бы иметь нестатические члены, что может быть безопаснее и, следовательно, предпочтительнее.

Если вы выбрали переменные шаблона просто для того, чтобы не повторять аргументы шаблона при создании объекта, то есть хорошие новости: начиная с C ++ 17, вы можете выводить аргументы шаблона класса из конструктора. Так что если вы делаете сделаете свой класс шаблоном:

template<class value_type>
class VectorPrinter { /* ... */ };

вы по-прежнему можете определять свои объекты без указания аргументов шаблона:

VectorPrinter vp1(v1); // fine with above template, too - since C++17

но не полагайтесь на статические элементы.

Если вы хотите поместить несколько VectorPrinter (шаблонная версия) разных типов в общий контейнер, вам нужно будет ввести общий базовый класс. Таким образом, в таком сценарии у вас есть выбор: не статические переменные (особенно: не меняющиеся числа), но полиморфизм или наоборот. У меня есть четкие личные предпочтения (это не значит, что я отказался бы от другого подхода, если бы оказался лучше в конкретном сценарии), но вам придется взвесить себя ...

0 голосов
/ 23 января 2019

В сообщении об ошибке довольно четко сказано, что вы должны сделать: укажите аргумент шаблона для vec.

  template<class value_type>
  VectorPrinter(const std::vector<value_type>& vec_)
  {
    // Using a reference here so we don't have to type all this again and again.
    auto& v = vec<value_type>;
    v = vec_;
    for (std::size_t i = 0; i < v.size(); ++i)
      std::cout << v[i] << std::endl;
  }

Вы также должны будете предоставить определение для вашего шаблона переменной:

template<class value_type>
std::vector<value_type> VectorPrinter::vec;

Вместе это должно дать вам то, о чем вы просите: https://godbolt.org/z/gVFvFw
(Является ли это хорошим дизайном для вашего варианта использования - это другой вопрос).

...