Alex A.
Alex A.

Reputation: 452

Second lambda function in template causes compile error (intellisense does not detect problems) - error C2988

I'm using the latest version of C++ (guess it is something between C++17 and C++20) available in visual studio enterprise 16.8 (but this error happening on previous versions too).

The following part of the code works correctly if exclude SquareMatrixInput<T> input_func = [](bool latest) { T temp; cin >> temp; return temp; } from the template (of course, I'm also exclude SquareMatrixInput<T> from classes code). Intellitrace satisfied, but the compiler swears.

Compiler's output:

error C2958: the left brace '{' found at 'my_code.cpp' was not matched correctly
error C2988: unrecognizable template declaration/definition
error C2059: syntax error: '>'
error C2988: unrecognizable template declaration/definition
error C2059: syntax error: 'return'
error C2988: unrecognizable template declaration/definition
error C2059: syntax error: '}'
error C2143: syntax error: missing ';' before '}'
error C7568: argument list missing after assumed function template 'SquareMatrix'

Code:

#include <iostream>

using namespace std;

template<typename T>
using SquareMatrixPrint = void (*)(const T& item, bool latest);

template<typename T>
using SquareMatrixInput = T (*)(bool latest);

template<typename T = int, 
    SquareMatrixPrint<T> print_func = [](const T &item, bool latest) { cout << item << (latest ? '\n' : '\t'); }, 
    SquareMatrixInput<T> input_func = [](bool latest) { T temp; cin >> temp; return temp; } >
class SquareMatrix {
    uint8_t grade;
    uint16_t size;
    T *items;
public:
    explicit SquareMatrix(uint8_t grade) {
        if (grade < 2) {
            throw new exception();
        }
        this->grade = grade;
        size = grade * grade;
        items = new T[size]{};
    }
    const T *operator[] (uint8_t i) const {
        return items + i * grade;
    }
    template <typename U, SquareMatrixPrint<U> pf, SquareMatrixInput<U> fi>
    SquareMatrix(const SquareMatrix<U, pf, fi> &sqm) {
        grade = sqm.GetGrade();
        size = grade * grade;
        items = new T[size];
        T *citem = items;
        for (uint8_t i = 0, j; i != grade; ++i) {
            for (j = 0; j != grade; ++j) {
                *citem = sqm[i][j];
                ++citem;
            }
        }
    }
    template <typename U, SquareMatrixPrint<U> pf, SquareMatrixInput<U> fi>
    const SquareMatrix<T, print_func, input_func>& operator=(const SquareMatrix<U, pf, fi> &sqm) {
        if (this == &sqm) return *this;
        if (grade != sqm.GetGrade()) {
            grade = sqm.GetGrade();
            size = grade * grade;

            delete[] items;
            items = new T[size];
        }
        T *citem = items;
        for (uint8_t i = 0, j; i != grade; ++i) {
            for (j = 0; j != grade; ++j) {
                *citem = sqm[i][j];
                ++citem;
            }
        }
        return *this;
    }
    ~SquareMatrix() {
        delete[] items;
    }
};

int main() {
    SquareMatrix<> sq(4);
    
    return 0;
}

The next code (if I removing defaults from the template) works:

int main() {
    SquareMatrix<int, [](const int &item, bool latest) { cout << item << (latest ? '\n' : '\t'); },
        [](bool latest) { int temp; cin >> temp; return temp; } > sq(4);
    
    return 0;
}

Upvotes: 1

Views: 445

Answers (3)

Jonathan Caves
Jonathan Caves

Reputation: 21

Hi: this is due to a bug in Visual C++ and the cause is the issue mentioned above - the compiler is treating '>>' as the terminator for the template parameter list. The bug has been fixed and should show up in the next update to Visual C++ 2019.

Upvotes: 2

Jarod42
Jarod42

Reputation: 217283

Parsing issue in template parameter with cin >> temp;

>> is (wrongly) interpreted as closing angle brackets of the template.

You have to put extra parenthesis:

(cin >> temp;)

Demo

Upvotes: 0

Adrian Mole
Adrian Mole

Reputation: 51835

I think it's a bug in the Visual Studio compiler (I can reproduce with Community Edition 2019). Clang-cl has no problem with your code.

The problem appears to be that the compiler is confused by the >> operator in cin >> temp; and can be fixed by enclosing that operation in parentheses, like so:

template<typename T = int,
    SquareMatrixPrint<T> print_func = [](const T& item, bool latest) { cout << item << (latest ? '\n' : '\t'); },
    SquareMatrixInput<T> input_func = [](bool) { T temp; (cin >> temp); return temp; } >
    class SquareMatrix {
    //...

Upvotes: 0

Related Questions