Не могу решить ошибку с2760 (непредвиденный токен)

Я делаю функцию для случайного заполнения двумерного массива. У меня есть класс Matrix(темплейтовый). Мне нужно в зависимости от типа данных который там находится поместить значение правильного типа.

Вот мой код:

void randomFill(int min = 0, int max = 10)
    {
        string typeID;
        typeID = (string)(typeid(type).name());
        
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                if (typeID == "int")        data[i][j] = rand() % (int)((max - min + 1) + min);
                else if (typeID == "float") data[i][j] = rand() % (float)((max - min + 1) + min);
                else if(typeID == "double") data[i][j] = rand() % (double)((max - min + 1) + min);
            }
        }
    }

type - это тип текущего класа.

У меня вылетает следующая ошибка:

Ошибка  C2760   синтаксическая ошибка: непредвиденный токен "идентификатор"; требуется ";"  

Код целиком:

template <typename type>
class Matrix
{
private:
    unsigned int row;
    unsigned int col;
    type** data;
public:
    ~Matrix()
    {
        for (size_t i = 0; i < row; i++)
        {
            delete[] data[i];
            data[i] = nullptr;
        }
        data = nullptr;
    }
    Matrix(int row, int col)
    {
        data = new type * [row];
        for (size_t i = 0; i < row; i++)
        {
            data[i] = new type[col];
        }
        this->row = row;
        this->col = col;

    }
    Matrix(const Matrix<type>& elem) : Matrix(elem.row, elem.col)
    {
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j
                = 0; j < col; j++)
            {
                data[i][j] = elem.data[i][j];
            }
        }


    }

    template <typename type>
    static void createArr2D(type**& init, int row, int col)
    {
        init = new type * [row];
        for (size_t i = 0; i < row; i++)
        {
            init[i] = new type[col];
        }
    }

    template <typename type>
    static void DeleteArr2D(type**& init, int row)
    {
        for (size_t i = 0; i < row; i++)
        {
            delete[] init[i];
            init[i] = nullptr;
        }
        init = nullptr;
    }

    static int MaxLenElemArr2D(type** init, int row, int col)
    {
        int res = 0;

        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                if (std::to_string(init[i][j]).size() > res) res = std::to_string(init[i][j]).size();
            }
        }
        return res;
    }

    friend std::ostream& operator<<(std::ostream& out, Matrix<type> p)
    {
        int maxLen = MaxLenElemArr2D(p.data, p.row, p.col);
        for (size_t i = 0; i < p.row; i++)
        {
            for (size_t j = 0; j < p.col; j++)
            {
                out << std::setw(maxLen+2) << p.data[i][j];
            }
            out << std::endl;
        }
        return out;
    }
    friend std::istream& operator>>(std::istream& in, Matrix<type>& p)
    {
        for (size_t i = 0; i < p.row; i++)
        {
            COORD coord;
            coord.Y = i + 1;
            for (size_t j = 0; j < p.col; j++)
            {
                if (j == 0) coord.X = j + 1;
                bool flag;
                do
                {
                    int tmp;
                    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

                    in >> tmp;
                    p.data[i][j] = tmp;

                    int size_tmpElem = std::to_string(tmp).size();
                    if (in.fail())
                    {
                        in.clear();
                        in.ignore(32767, '\n');
                        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
                        for (size_t i = 0; i < 100; i++) std::cout << " ";
                        flag = true;
                    }
                    else
                    {
                        flag = false;
                        coord.X += size_tmpElem + 2;
                    }
                } while (flag);
            }
        }
        return in;

    }

    friend Matrix operator+(Matrix<type>& first, Matrix<type>& second)
    {
        /*  if (first.row != second.col || first.row != second.row) return;*/

        Matrix<type> tmp(first.row, first.col);

        for (size_t i = 0; i < first.row; i++)
        {
            for (size_t j = 0; j < first.col; j++)
            {
                tmp.data[i][j] = first.data[i][j] + second.data[i][j];
            }
        }
        return tmp;
    }
    friend Matrix operator-(Matrix<type>& first, Matrix<type>& second)
    {
        /*  if (first.row != second.col || first.row != second.row) return;*/

        Matrix<type> tmp(first.row, first.col);

        for (size_t i = 0; i < first.row; i++)
        {
            for (size_t j = 0; j < first.col; j++)
            {
                tmp.data[i][j] = first.data[i][j] - second.data[i][j];
            }
        }
        return tmp;
    }
    friend Matrix operator*(Matrix<type>& first, Matrix<type>& second)
    {
        /*  if (first.row != second.col || first.row != second.row) return;*/

        Matrix<type> tmp(first.row, first.col);

        for (size_t i = 0; i < tmp.row; i++)
        {
            for (size_t j = 0; j < tmp.col; j++)
            {
                tmp.data[i][j] = first.data[i][j] * second.data[i][j];
            }
        }
        return tmp;
    }
    friend Matrix operator/(Matrix<type>& first, Matrix<type>& second)
    {
        /*  if (first.row != second.col || first.row != second.row) return;*/

        Matrix<type> tmp(first.row, first.col);

        for (size_t i = 0; i < first.row; i++)
        {
            for (size_t j = 0; j < first.col; j++)
            {
                if (second.data[i][j] == 0) tmp.data[i][j] = 0;
                else tmp.data[i][j] = first.data[i][j] / second.data[i][j];
            }
        }
        return tmp;
    }

    /*Matrix& operator=(Matrix<type>& second)
    {
        if (data != nullptr)
        {
            clear();
        }
        row = second.row;
        col = second.col;

        data = new type * [row];
        for (size_t i = 0; i < col; i++)
        {
            data[i] = new type[col];
        }

        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                data[i][j] = second.data[i][j];
            }
        }
        return *this;
    }*/
    Matrix& operator=(Matrix<type> second)
    {
        if (data != nullptr)
        {
            clear();
        }
        row = second.row;
        col = second.col;

        data = new type * [row];
        for (size_t i = 0; i < col; i++)
        {
            data[i] = new type[col];
        }

        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                data[i][j] = second.data[i][j];
            }
        }
        return *this;
    }
    friend bool operator==(Matrix<type>& first, Matrix<type>& second)
    {
        if (first.row != second.row || first.col != second.col) return false;

        for (size_t i = 0; i < first.row; i++)
        {
            for (size_t j = 0; j < first.col; j++)
            {
                if (first.data[i][j] != second.data[i][j]) return false;
            }
        }
        return true;
    }
    friend bool operator!=(Matrix<type>& first, Matrix<type>& second)
    {
        if (first.row != second.row || first.col != second.col) return true;

        for (size_t i = 0; i < first.row; i++)
        {
            for (size_t j = 0; j < first.col; j++)
            {
                if (first.data[i][j] != second.data[i][j]) return true;
            }
        }
        return false;
    }


    void clear()
    {
        for (size_t i = 0; i < row; i++)
        {
            delete[] data[i];
            data[i] = nullptr;
        }
        data = nullptr;
        row = 0;
        col = 0;
    }

    void randomFill(int min = 0, int max = 10)
    {
        /*string typeID;
        typeID = (string)(typeid(type).name());*/
        
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                data[i][j] = rand() % (int)((max - min + 1) + min);
                /*if (typeID == "int")      data[i][j] = rand() % (int)((max - min + 1) + min);
                else if (typeID == "float") data[i][j] = rand() % (float)((max - min + 1) + min);
                else if(typeID == "double") data[i][j] = rand() % (double)((max - min + 1) + min);*/
            }
        }
    }

    void print()
    {
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                std::cout << std::setw(3) << data[i][j];
            }
            std::cout << std::endl;
        }
    }

    void transposition()
    {
        type** NewData = new type * [col];

        // создаем новый массив с реверсивным количеством строк и колонок
        for (size_t i = 0; i < col; i++)
        {
            NewData[i] = new type[row];
        }

        // Перенос данных
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                NewData[j][i] = data[i][j];
            }
        }

        // Очищаем прошлые данные 
        for (size_t i = 0; i < row; i++)
        {
            delete[] data[i];
            data[i] = nullptr;
        }
        data = nullptr;

        std::swap(row, col);

        // Присваиваем указатель на старое место 
        data = NewData;
    }

    void KbInput(int posX = 0, int posY = 0)
    {
        for (size_t i = 0; i < row; i++)
        {
            COORD coord;
            coord.Y = i + 1 + posY;
            for (size_t j = 0; j < col; j++)
            {
                if (j == 0) coord.X = j + 1 + posX;
                bool flag;
                do
                {
                    int tmp;
                    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

                    std::cin >> tmp;
                    data[i][j] = tmp;

                    int size_tmpElem = std::to_string(tmp).size();
                    if (std::cin.fail())
                    {
                        std::cin.clear();
                        std::cin.ignore(32767, '\n');
                        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
                        for (size_t i = 0; i < 100; i++) std::cout << " ";
                        flag = true;
                    }
                    else
                    {
                        flag = false;
                        coord.X += size_tmpElem + 2;
                    }
                } while (flag);
            }
        }

    }

    unsigned int getRow() const { return row; }
    unsigned int getCol() const { return col; }

    void DelRow(int pos)
    {
        if (pos < 0 || pos > row - 1) return;

        type** NewData = new type * [row - 1];

        createArr2D(NewData, row - 1, col);

        if (pos != 0)
        {
            for (size_t i = 0; i < pos; i++)
            {
                for (size_t j = 0; j < col; j++)
                {
                    NewData[i][j] = data[i][j];
                }
            }
        }
        
        for (size_t i = pos+1, i_posNew = pos; i < row ; i++, i_posNew++)
        {
            for (size_t j = 0, j_posNew = 0; j < col; j++, j_posNew++)
            {
                NewData[i_posNew][j_posNew] = data[i][j];
            }
        }
    
        DeleteArr2D(data, row);
        data = NewData;
        row--;
    }

    void DelCol(int pos)
    {
        if (pos < 0 || pos > col - 1) return;

        type** NewData; 
        createArr2D(NewData, row, col - 1);

        if (pos != 0)
        {
            for (size_t i = 0; i < row; i++)
            {
                for (size_t j = 0; j < pos; j++)
                {
                    NewData[i][j] = data[i][j];
                }
            }
        }
    
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = pos+1, j_NewData = pos; j < col; j++, j_NewData++)
            {
                NewData[i][j_NewData] = data[i][j];
            }
        }

        DeleteArr2D(data, row);
        data = NewData;
        col--;
    }

    type findMaxElem()
    {
        type res = data[0][0];
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                if (data[i][j] > res) res = data[i][j];
            }
        }
        return res;

    }

    type findMinElem()
    {
        type res = data[0][0];
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col; j++)
            {
                if (data[i][j] < res) res = data[i][j];
            }
        }
        return res;
    }

    void lineByline_Sort()
    {
        for (size_t i = 0; i < row; i++)
        {
            for (size_t j = 0; j < col-1; j++)
            {
                int min = j;
                for (size_t b = j+1; b < col; b++)
                {
                    if (data[i][b] < data[i][min])
                        min = b;
                }
                std::swap(data[i][j], data[i][min]);
            }
        }
    }
    void Full_Sort()
    {
        for (size_t i_swap = 0; i_swap < row; i_swap++)
        {
            for (size_t j_swap = 0; j_swap < col; j_swap++)
            {
                int row_min = i_swap;
                int col_min = j_swap;
                for (size_t i = row_min; i < row; i++)
                {
                    if (i == row_min)
                    {
                        for (size_t j = col_min + 1; j < col; j++)
                        {
                            if (data[i][j] < data[row_min][col_min])
                            {
                                row_min = i;
                                col_min = j;
                            }
                        }
                    }
                    else
                    {
                        for (size_t j = 0; j < col; j++)
                        {
                            if (data[i][j] < data[row_min][col_min])
                            {
                                row_min = i;
                                col_min = j;
                            }
                        }
                    }
                }
                std::swap(data[i_swap][j_swap], data[row_min][col_min]);
                /*std::cout << std::endl << std::endl;
                print();*/
            }
            
        }
        
    }
};

Ответы (2 шт):

Автор решения: KoVadim

Если закрыть глаза на кучи других "странностей", то Ваша проблема в том, что Вы подключили Windows.h (о котором Вы умолчали в так называемом "полном коде"). А оно определяет макросы min/max. А у Вас так называются параметры....

void randomFill(int min = 0, int max = 10)

после того, как тут поработает препроцессор, Вы не узнаете этого кода.

Что делать? да просто назовите эти параметры по другому или перед #include <Windows.h> добавьте такую странную строку #define NOMINMAX (да да, именно строкой выше, можно и на две. Но ни в коем случае не ниже).

Также похоже в коде есть две лишние строки template <typename type>, там типы совпадают с вышестоящим. Я думаю, эти строки просто не нужны, либо там должен быть немного переписан код. Но это уже Вам виднее.

→ Ссылка
Автор решения: Harry

Я бы не заморачивался с ненадежным typeid, тем более что переносимости он не даст ни малейшей, и делал так - чтобы решать вопрос во время компиляции, а не дорогой ценой во время выполнения:

void randomFill(type min = 0, type max = 10)
{
    for (size_t i = 0; i < row; i++)
    {
        for (size_t j = 0; j < col; j++)
        {
            if constexpr (is_integral_v<type>)
            {
                data[i][j] = rand() % (max - min + 1) + min;
            }
            else
            {
                data[i][j] = (max - min)*rand()/RAND_MAX + min;
            }
        }
    }
}

А еще точнее - я бы делал не так, а с использованием #include<random> и нормальными генераторами распределений, которые для заданного типа type выполняли бы всю работу самостоятельно.

И еще - я бы сразу добавил проверку, чтоб типы были разрешены только числовые, а то у вас можно и матрицы строк или, скажем, векторов сделать случайно :)

Добиться этого можно, например, объявив класс так:

template <typename type,
          typename = enable_if_t<is_arithmetic_v<type>>>
class Matrix
...

Все, после этого вы сможете создавать Matrix только для арифметических типов.

→ Ссылка