Неизвестный тип возвращаемых шаблонных функций, повторение кода при использовании decltype - PullRequest
4 голосов
/ 01 апреля 2019

В моей работе есть несколько шаблонных математических классов (например, матрицы).

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

Двойной объект может взаимодействовать только с другим двойным объектом.Для этого функция convert () была реализована для различных типов, с реализацией, подобной этой:

Matrix<T2> convert(const Matrix<T1>& m, T2 dummy) {
   // create a matrix with type T2 and cast m values into it 
   //  retMatrix(i, j) = (T2)m(i,j)
} 

Вы бы назвали ее с помощью:

auto floatMatrix = convert(doubleMatrix, 0.f);

Или чуть более многословно:

auto floatMatrix = convert(doubleMatrix, float());

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

template <typename T, typename S>
auto convert(S&& s) -> decltype(convert(s, T())) {
  return convert(s, T());
} 

Теперь их можно вызывать с помощью:

auto floatMatrix = convert<float>(doubleMatrix);

Мой вопрос в том, что моя сигнатура функции довольно неловкая, мне нужно повторить convert(s, T()) как в типе decl, так и в реальном теле функции

Как мне преодолеть это?

спасибо

edit:

в настоящее время мы не используем c ++ 14

edit # 2:

класс Matrix былпросто пример, есть довольно много соответствующих классов, для которых реализована функция convert ().Каждый из них уже "специализирован", как кто-то предложил в ответе ниже (тем временем удалено).Я хотел бы настроить способ вызова convert () без повторной реализации всего

edit # 3:

поддерживаемые типы, очевидно, отличаются только от float и double.пожалуйста, рассмотрите пример, который я привел, а не реальную проблему, которую я пытаюсь решить

«фиктивные» функции уже реализованы, я пытался заставить их работать с минимальными усилиями вместо рефакторинга 30функции и все виды использования

Я не думаю, что этот вопрос слишком надуман, учитывая, что cpp14 позволяет просто удалить -> decltype() thingy ...

Ответы [ 2 ]

1 голос
/ 01 апреля 2019

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

Matrix<double> convert(const Matrix<float>& m) {
    // ...
}

Matrix<float> convert(const Matrix<double>& m) {
    // ...
}

float-> float и double-> double не кажутся осмысленными операциями, которые необходимо сохранить, так что на самом деле создание ошибки компилятора представляется полезным (в то время как механизм шаблонов может на самом деле преуспеть и просто создать ненужную копию).

Кроме того, потребность в фиктивном параметре, во-первых, сбивает с толку без более полного примера.

Если вы настроены на шаблоны (например, типы выходят за рамки этих двух):

template <typename T2, typename T1>
Matrix<T2> convert(const Matrix<T1>& m) {
}

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

0 голосов
/ 01 апреля 2019

Одной из опций могут быть вспомогательные классы, которые знают тип преобразования из Matrix for T в Matrix, но они не более красивы, чем оператор decltype, который является читаемым и локальным для кода.

Может ли Matrix наследоваться от базового класса, который знает, как генерировать Matrix из T? Возможно, в качестве члена, так что вы можете написать:

class MatrixBase
{
  public:
    template <class T> class To 
   { typedef Matrix<T> To; };
};

class Matrix<int>:public MatrixBase {
  // ...
};

Все это просто написать: -> S::To<T>::To

Как вы говорите, с революцией в C ++ 14 вы можете сделать полностью автоматический тип возвращаемого значения.

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