user1801060
user1801060

Reputation: 2821

error: expected primary-expression before ‘,’

I'm a C++ newbie. I want to determine the size of string array in C++. Following advice on this forum, I've created a template to give me the size of the array. The releavant code is

virtual std::string _verify_list_or_string(std::string obj[]) {     
    std::cout << "debug " << sizeof_array(std::string, sizeof(obj)) << std::endl;

The template I'm using is

template <typename T, std::size_t N>
std::size_t sizeof_array( T (&)[N] ) {
   return N;
}

I get a compile error: "error: expected primary-expression before ‘,’"

What am I doing wrong?

Upvotes: 0

Views: 1897

Answers (4)

Mike Seymour
Mike Seymour

Reputation: 254751

The problem is that, despite the [], the function argument is a pointer and not an array. You can only pass an array to a function by reference, and then it must be a reference to a specific size of array - the size is part of the array's type.

If you need the size of an array that's been passed as a pointer, then some options are:

  • make the function itself a template, like your sizeof_array, so that the array is passed by reference and the size available as a template parameter;
  • make the function a template taking an iterator range in two arguments, so it can be used with any kind of sequence (including arrays);
  • pass the size of the array as a second argument;
  • pass a class type like std::array or std::vector with an interface that can give you the size.

The error is because you're passing nonsense to sizeof_array. If obj were an array, then you'd do sizeof_array(obj), and the template arguments would be inferred from the type of obj. But it isn't an array, so that won't work either.

Upvotes: 3

awesoon
awesoon

Reputation: 33701

Your function takes one parameter:

std::size_t sizeof_array( T (&)[N] )
//                       ^^^^^^^^^^

But you're passing two. Moreover, one of them - type:

sizeof_array(std::string, sizeof(obj))
//           ^^^^^^^^^^^^ ^^^^^^^^^^^

You'd probably want to pass an obj variable. But the problem is that obj is not an array here. So, you can't get size of obj this way.

Upvotes: 2

Ben Voigt
Ben Voigt

Reputation: 283921

That's not how you invoke a template function... arguments, not template parameters go inside the function-call parentheses. That function is designed to infer the template parameters. If inference wasn't possible, you'd call like this:

std::string ary[6];
sizeof_array<std::string, 6>(ary);

Since inference is possible, the compiler will figure out the template parameters if you just pass the argument:

sizeof_array(ary);

Unfortunately for you, that template function only works on arrays, but you have a pointer. There's no size information for you to get to.

Upvotes: 0

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 154045

The problematic expression is sizeof_array(std::string, sizeof(obj)): std::string isn't an expression but a type. Fixing that expression won't help, though: the argument obj isn't a suitable argument for sizeof_array() because it has type std::string* while sizeof_array() takes an array reference as argument.

Once the array has decayed into a pointer there is no way to recover the array size. If you want to automatically determine the size of an array in a function, you need to pass the array by reference, e.g.:

template <int Size>
std::string _verify_list_or_string(std::string (&obj)[Size]) {
    std::cout << "debug " << sizeof_array(obj) << '\n';
    return _verify_list_or_string(obj, Size);
}
virtual std::string _verify_list_or_string(std::string* obj, int Size) {
    ...
}

Note that the primary entry point was turned into a template which can't be virtual. Thus, it forwards to a virtual function taking a pointer to the array and its size.

Upvotes: 2

Related Questions