Шаблонные конструкторы в классе шаблона - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь реализовать класс Matrix, определяя строки и столбцы в качестве параметров шаблона.Кроме того, я рассматриваю Vector как «деградированный» матричный класс, который разделяет большую часть его кода.

Я хотел бы инициализировать свои классы, используя списки инициализаторов, как это использовалось старым способом c массивами.

Проблема возникает при попытке дать одному и только одному конструктору класс в зависимости от того, является ли он Матрицей или Вектором, поэтому во время компиляции запрещается присваивать список инициализирующих матриц для вектора, а список инициализирующих векторов - для вектора.матрица.Я пытался с шаблонами и с std :: enable_if, но я не в состоянии полностью понять странные сообщения об ошибках компилятора.

Я публикую сокращенный код с указанием проблемы, очистить от всех испытаний для решенияЭто.В комментарии я включаю дальнейшее объяснение того, что я пытаюсь сделать.Кто-нибудь может знает, как сделать то, что мне нужно?

#include <initializer_list>     

template<int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<T> initializers) { }//Do some stuff inside
    Matrix(std::initializer_list<std::initializer_list<T>> initializers) { }//Do some stuff inside
};

template<int R, typename T=int>
using Vector = Matrix<R, 1, T>;

int main()
{
    Matrix<3, 3> m = { {1, 2, 3},
                       {4, 5, 6},
                       {7, 8, 9} };

    Vector<3> v = {10, 20, 30};

    Matrix<3, 3> m1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//This must be avoided using templates in constructors or SFINAE 
    Vector<3> v1 = { {10, 20, 30} };//This must be avoided using templates in constructors or SFINAE

    return 0;   
}

Кроме того, я выкладываю ссылку coliru с таким же кодом: http://coliru.stacked -crooked.com / a / 17b5e8c504c262d1

Заранее большое спасибо.

1 Ответ

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

С C ++ 20 вы можете использовать requires для сброса перегрузок:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<T> initializers) requires (C == 1)
    { /*..*/ }

    Matrix(std::initializer_list<std::initializer_list<T>> initializers) requires (C != 1)
    { /*..*/ }
};

Демо

До этого специализация:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    Matrix(std::initializer_list<std::initializer_list<T>> initializers)
    { /*..*/ }
};

template <int R, typename T>
struct Matrix<R, 1, T>
{
    T data[R][1];

    Matrix(std::initializer_list<T> initializers)
    { /*..*/ }
};

или SFINAE можно использовать:

template <int R, int C, typename T=int>
struct Matrix
{
    T data[R][C];

    template <typename D = C, std::enable_if_t<D == 1, int> = 0>
    Matrix(std::initializer_list<T> initializers)
    { /*..*/ }

    template <typename D = C, std::enable_if_t<D != 1, int> = 0>
    Matrix(std::initializer_list<std::initializer_list<T>> initializers)
    { /*..*/ }
};
...