Использование С++ с использованием: Что я здесь делаю неправильно?

Следующий код не компилируется в последней версии Microsoft Visual Studio. Может ли кто-нибудь просветить меня, что я здесь делаю неправильно?

#include <iostream>
#include <iomanip>
#include <array>

template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<T, M * N>;

template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
    for (auto i = 0; i < M; ++i)
    {
        for (auto j = 0; j < N; ++j)
        {
            os << std::setw(5) << matrix[i * N + j];
        }

        os << std::endl;
    }

    return os;
}

int main(int argc, const char * const argv[])
{
    Matrix<float, 2, 3> matrix{
        1.1f, 1.2f, 1.3f,
        2.1f, 2.2f, 2.3f
    };

    std::cout << matrix << std::endl;

    return 0;
}

Вот снимок ошибки компилятора:

1>main.cpp(30): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'std::array<T,6>' (or there is no acceptable conversion)
1>          with
1>          [
1>              T=float
1>          ]

Изменить: работает следующий код:

#include <iostream>
#include <iomanip>
#include <array>

template <typename T, std::size_t M, std::size_t N>
using Matrix = std::array<std::array<T, N>, M>;

template <typename T, std::size_t M, std::size_t N>
std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &matrix)
{
    for (auto row : matrix)
    {
        for (auto element : row)
        {
            os << std::setw(5) << element;
        }

        os << std::endl;
    }

    return os;
}

int main(int argc, const char * const argv[])
{
    Matrix<float, 2, 3> matrix{
        1.1f, 1.2f, 1.3f,
        2.1f, 2.2f, 2.3f
    };

    std::cout << matrix << std::endl;

    return 0;
}

person 0ca6ra    schedule 12.10.2015    source источник
comment
С N*M в параметре шаблона вашего operator<< (косвенно через std::array) невозможно вывести N и M независимо друг от друга. Обратите внимание, что экземпляры псевдонимов типов эквивалентны типу, на который они ссылаются, то есть ваш второй параметр operator<< эквивалентен const std::array<T, M*N> &matrix   -  person dyp    schedule 12.10.2015
comment
@dyp, может быть, тебе стоит дать ответ   -  person Lol4t0    schedule 12.10.2015
comment
спасибо, теперь я ясно вижу!   -  person 0ca6ra    schedule 12.10.2015
comment
аналогичные шаблоны псевдонимов C++11 в CUDA   -  person Piotr Skotnicki    schedule 12.10.2015


Ответы (1)


Принимая во внимание комментарий @dyp, вам нужно создать новый тип вместо алиаса, который будет иметь 2 независимых параметра.

Таким образом, вы просто используете агрегацию, включая фактические данные в качестве поля, например:

template <typename T, std::size_t M, std::size_t N>
class Matrix
{
private:
    std::array<T, M * N> _data;
    template <typename T1, std::size_t M1, std::size_t N1> friend std::ostream &operator<<(std::ostream &os, const Matrix<T1, M1, N1> &matrix);
public:
    template <typename...Args>
    Matrix(Args... args):
        _data{{std::forward<Args>(args)...}}
    {}
};
person Lol4t0    schedule 12.10.2015