С ++ создаст несколько экземпляров функции из шаблона с нетиповыми параметрами - PullRequest
0 голосов
/ 06 июня 2019

Я недавно узнал о шаблонах c ++ и тестировал их с помощью класса матрицы:

template<typename T>

class Matrix
{
    public:
        Matrix();

        int width;
        int height;

        Matrix operator*(const Matrix& rMatrix)
        Matrix operaor+(const Matrix& rMatrix)

        // other matrix operations/functions here
    private:
        T* data;
};

Затем я обнаружил, что шаблоны могут принимать нетиповые параметры, что позволяет мне сделать это:

template<typename T, int width, int height>

class Matrix
{
    public:
        Matrix();

        template <int width2>
        Matrix<T, width2, height> operator*(const Matrix<width2, width>7 rMatrix)

        // other matrix operations/functions here

    private:
        T* data;
};

Я подумал, что последний, вероятно, был бы лучше, если бы вы знали все размеры, которые вам понадобятся во время компиляции, поскольку это приведет к ошибкам компиляции, если матрицы имеют неправильный размер (для операций умножения / сложения), тогда как первый заставил меня проверить это во время выполнения. Однако меня беспокоило, что компилятор будет генерировать разные функции для добавления 4x4 к 4x4 против 3x3 к 3x3 (при условии, что оба имеют один и тот же тип), что будет неэффективно.

Итак, мой вопрос заключается в следующем: будет ли используемый мной компилятор (g ++) генерировать несколько функций из шаблона, если есть изменение в параметре нетипичного типа (в приведенном выше примере ширина / высота матрицы)?

редактирование / уточнение:

  • функции не определены inline (они находятся в отдельном файле .tpp)
  • под 'неэффективным' я подразумеваю, что (насколько я понимаю) наличие этих изменений в функции приведет к тому, что скомпилированный исполняемый файл будет больше, чем в противном случае

1 Ответ

0 голосов
/ 06 июня 2019

Взгляните на C ++ Insights .

Если вы вставите туда свой код и добавите функцию main, которая использует два типа матриц с разной высотой и шириной (см. здесь и нажмите кнопку «Воспроизвести»), вы можете увидеть, что компилятор генерирует:

template<typename T, int width, int height>
class Matrix
{
public:
    Matrix();

    template <int width2>
    Matrix<T, width2, height> operator*(const Matrix<T, width2, width> rMatrix);

    // other matrix operations/functions here

private:
    T* data;
};

/* First instantiated from: insights.cpp:18 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Matrix<double, 1, 2>
{

public: 
  Matrix();

  template<int width2>
  Matrix<double, width2, 2> operator*(const Matrix<double, width2, 1> rMatrix);

private: 
  double * data;
public: 
  // inline constexpr Matrix(const Matrix<double, 1, 2> &) = default;
  // inline constexpr Matrix(Matrix<double, 1, 2> &&) = default;
};

#endif


/* First instantiated from: insights.cpp:19 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
class Matrix<double, 2, 1>
{

public: 
  Matrix();

  template<int width2>
  Matrix<double, width2, 1> operator*(const Matrix<double, width2, 2> rMatrix);

private: 
  double * data;
public: 
  // inline constexpr Matrix(const Matrix<double, 2, 1> &) = default;
  // inline constexpr Matrix(Matrix<double, 2, 1> &&) = default;
};

#endif


int main()
{
  Matrix<double, 1, 2> Matrix1 = Matrix<double, 1, 2>();
  Matrix<double, 2, 1> Matrix2 = Matrix<double, 2, 1>();
}

Следовательно, да, создаются версии для всех комбинаций ширины и высоты, используемых где-то еще в коде.

...