3

I tried to get the length of the string array, and I've done it in the main function and it worked. Afterwards I needed to do so in a function, but it doesn't identifies the functions with error:

IntelliSense: no instance of overloaded function "begin" matches the argument list

code:

void fun(string arr[])
{
    cout << end(arr) - begin(arr);
}

void main()
{
    string arr[] = {"This is a single string"};
    fun(arr);
}

also for the end.

So I added the pointer symbol '*' and the error disappeared, but it returns me the length of the first item in the array.

Why do I get this error? How to fix it?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
user2410243
  • 187
  • 3
  • 12

2 Answers2

5

You can do this via

#include <iostream>
#include <string>

template<size_t N>
void fun(std::string (&arr)[N])
{
    std::cout << std::end(arr) - std::begin(arr);
}

int main (void)
{
    std::string arr[] = {"This is a single string"};
    fun(arr);
}

But in your example the array is decaying into a pointer so you can't call sizeof, begin or end.

Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • +1? That's type system abuse, the conventional way of passing vanilla arrays around is as (begin, length) or (begin, end). – Kos Jan 17 '14 at 13:30
  • That's at least debatable. I don't think that passing an array by reference is type system abuse. Furthermore, I think one should stick to `std::array` or `std::vector` instead of "vanilla arrays" in terms of modern C++ if possible. But that's not the question. – Pixelchemist Jan 17 '14 at 13:51
  • @Pixelchemist Indeed, with this approach, you can just use `N`, but OP's approach was given as an answer from his previous question, but no one told him it wouldn't work as soon as you passed it to a function. –  Jan 17 '14 at 13:52
  • @remyabel The answer of juanchopanza to the previous question actually covers passing a reference to the array into a function correctly. So there was no need to tell him that it won't work when passed to a function since that's what it does: it works as intended. – Pixelchemist Jan 17 '14 at 13:59
  • @Kos: Can't be done with string literals, for instance. There is value to this idiom. I +1'ed an said "There we go" because this precisely answers the question as asked, without changing the conditions of the question, after several other people's failed attempts. Your answer would be equally valid in my eyes. – John Dibling Jan 17 '14 at 14:01
2

The problem is that you're not really working on an array of string... You're working with a pointer on a std::string, because std::string arr[] decays to std::string*.

So what it means is just std::end() and std::begin() don't work for pointers.

The workaround I prefer is to use std::array<> or std::vector<> or to retrieve begin end before calling the function:

template <typename iterator>
void fun(iterator begin, iterator end)
{
    std::cout << end - begin; 
}

int main()
{
    std::string arr[] = {"This is a single string"};
    fun(std::begin(arr), std::end(arr));
    return 0;
}

I do not like having the size hardcoded in a parameter like suggested in another answer, but it is a matter of personal taste.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Johan
  • 3,728
  • 16
  • 25