Есть ли способ определить элемент шаблона в не шаблонном классе? - PullRequest
8 голосов
/ 26 марта 2019

Скажем, у меня есть шаблон класса с именем Compute и другой класс с именем Function_A с шаблоном функции-члена:

template <typename T> void Evaluate(T parameter)

Я вынужден использовать класс Function_A как есть. Я уже знаю, что T может быть только одного из двух типов type_1 и type_2.

Есть ли способ иметь нечто подобное Compute<T> C в качестве переменной-члена Function_A вместо определения локального Compute<T> объекта внутри Evaluate(...)? Я знаю, что это противоречит философии использования шаблонов, следовательно, это, вероятно, невозможно, но в идеале в этом случае лучше сделать это?

Я попытался создать два члена Compute<type_1> C1 и Compute<type_2> C2 в Function_A, а затем использовать их под if (typeid(T) == typeid(type_1)), но это довольно отвратительно и вопреки философии использования шаблонов.

Просто чтобы проиллюстрировать, что я имею в виду:

template <class T>
class Compute
{
public:
  T Function_B(T parameter)
    {
      return f.eval(parameter);
    }

private:
  SomeClass<T> f;
}

И класс:

class Function_A
{
  public:
    template <typename T> T Evaluate(T parameter)
    {
      Compute<T> C; //this is very expensive!
      T value = C.Function_B(parameter);
      return value;
    }

  private:
    double SomeParameter;
    //Compute<T> C; //conceptually what I want
}

Ответы [ 2 ]

10 голосов
/ 26 марта 2019

Как насчет (не проверено):

class Function_A
{
  public:
    template <typename T> void Evaluate(T parameter)
    {
      T value = std::get<Compute<T>>(computers).Function_B(parameter);
      return T(SomeParameter) * value;
    }

  private:
    double SomeParameter;
    std::tuple<Compute<type_1>, Compute<type_2>> computers;
};

Примечание: std::pair будет работать точно так же, как std::tuple здесь, если вам нравится первая / вторая семантика, которую он добавляет.

Кроме того, обратите внимание, что T(SomeParameter) - это приведение в стиле C, что может быть проблематично, если T не является типом класса. Рассмотрим T{} или static_cast<T>().

4 голосов
/ 26 марта 2019

Одна вещь, которую вы можете сделать, это сделать C static.Если у вас есть

template <typename T> void Evaluate(T parameter)
{
  static Compute<T> C; // only do this once per T now
  T value = C.Function_B(parameter);
  return T(SomeParameter)*value;
}

, то при вызове Evaluate с type_1 у вас будет одна версия функции с C<type_1>, которая будет сконструирована только при первом запуске функции.называется и то же самое происходит для type_2.

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