1

I wrote a template function, that should take a reference to array of const elements, that has certain size. But for some reason the compiler says that this function doesn't match, when I call it

#include<iostream>

struct Node
{
    int key, left, right;
};

template <int N>
bool isCorrect(const Node (&nodes)[N])
{
    // doesn't matter
    return true;
}

int main ()
{
    int n;
    std::cin >> n;
    Node nodes[n];
    std::cout << (isCorrect(nodes) ? "CORRECT" : "iNCORRECT") << '\n';

    return 0;
}

It gave me a rather mysterious error message that I couldn't decipher:

"candidate template ignored couldn't match **Node** against **Node"**.

I pretty sure that template can be used to determine array size, like I'm trying to do, but this fails.

Is this due to the fact that I use a non-primitive type?

Yes, I know I can use vector and avoid this problem altogether. But I really want to know what the hell is going on when compiler can't match a type against itself.

What I can do to avoid this strange message in future?

AndyG
  • 39,700
  • 8
  • 109
  • 143
igor Smirnov
  • 188
  • 2
  • 8
  • 1
    Maybe a [dupe](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard)? Especially [this answer](https://stackoverflow.com/a/21519062/9593596) comments on the implications of vla on the type system. – lubgr Apr 15 '19 at 17:59
  • 4
    `Node nodes[n];` is not valid C++. –  Apr 15 '19 at 17:59
  • 3
    `Node nodes[n];` is not legal C++ code. Turn on `-pedantic` and you'll get a warning/error. If you need a run time sized array use a `std::vector` – NathanOliver Apr 15 '19 at 17:59

1 Answers1

4

When you write this:

int n;
std::cin >> n;

You are assigning a value to n at runtime.

However, template arguments must be known at compile-time. This is because the compiler needs them in order to generate the function (that it will then compile and export to your library).

The syntax:

Node nodes[n];

is called a Variable Length Array, and it's a compiler extension. It's not portable C++. The compiler makes it look like a regular array, but it's not.

To fix your problem, n must be known at compile time:

constexpr int n = 1;
Node nodes[n];
std::cout << (isCorrect(nodes) ? "CORRECT" : "iNCORRECT") << '\n';

Live Demo

AndyG
  • 39,700
  • 8
  • 109
  • 143