using range-for loop: too few arguments to function call, single argument 'a' was not specified

2.2k Views Asked by At

I'm a beginner in C++ and I'm reading section 3.4.1 Parameterized Types of the C++ programming language 4th ed by Bjarne Stroustrup.

What this chapter tries to show is defining the begin() and end() function in the user-defined type Vector so that a range-for loop(i.e. for (auto& s: vs )) is supported .

After defining the begin() and end() functions. I'm getting the error too few arguments to function call, single argument 'a' was not specified when I put them into use.

Version 1

The text really had this:

In user.cpp:

void f2(const Vector<string> & vs)
{
    for (auto& s: vs)          //member function 'begin' not viable: 'this' argument has type 'const Vecto<Std::__1::basic_string<char> >
        cout << s << '\n';
}

Xcode then tells me that member function 'begin' not viable: 'this' argument has type 'const Vecto<Std::__1::basic_string<char> >', but function is not marked const.

So I went ahead and marked the functions const.

In Vector.h:

template<typename T>
class Vector{
    public:
        const T* begin(Vector<T>& a);
        const T* end(Vector<T>& b);
};

In Vector.cpp:

#include "Vector.h"      //get the interface
//To support the range-for loop for our Vector, we must define suitable begin() and end() functions:
template <typename T>
const T* Vector<T>::begin(Vector<T>& x)
{
    return & x[0];
}
template <typename T>
const T* Vector<T>::end(Vector<T>& x)
{
    return x.begin()+x.size(); //pointer to one past last element.
}

The error persists.

Version 2

The next thing that i did was remove const from function f2(). I get this new error too few arguments to function call, single argument 'a' was not specified. Removing const from the functions in Vector.h and Vector.cpp didn't make any difference.

In user.cpp:

#include "Vector.h"
void f2(Vector<string> & vs)
{
    for (auto& s: vs)                    //too few arguments to function call, single argument 'a' was not specified
        cout << s << '\n';
}

In Vector.h:

template<typename T>
class Vector{
    public:
        const T* begin(Vector<T>& a);
        const T* end(Vector<T>& b);
};

In Vector.cpp:

#include "Vector.h"       //get the interface
//To support the range-for loop for our Vector, we must define suitable begin() and end() functions:
template <typename T>
const T* Vector<T>::begin(Vector<T>& x)
{
    return & x[0];
}
template <typename T>
const T* Vector<T>::end(Vector<T>& x)
{
    return x.begin()+x.size(); //pointer to one past last element.
}

I have included parts of the code that I think are most critical, otherwise, full codes are available here.

2

There are 2 best solutions below

0
On BEST ANSWER

So I went ahead and marked the functions const.

You didn't mark your member functions const. Besides that, they should be parameterless. For that, you need

const T* begin() const;
                 ^^^^^

Note that you need to make the implementation available in the header file, not in a separate .cpp file (unless you include that at the bottom of the header, and make sure there is no attempt to compile it.) It also makes sense to provide non-const overloads.

template<typename T>
class Vector{
    public:
        const T* begin() const {return &x[0]; }
        const T* end() const { return &c[0] + size(); }

        T* begin() {return &x[0]; }
        T* end()   { return &c[0] + size(); }

        size_t size() const { /* return the size */ }
};
0
On

You have two different problems. The first one with the constness is because your begin and end functions are not marked as const which makes them not callable on a constant object. Change declaration and definition to

const T* begin(Vector<T>& a) const;
const T* end(Vector<T>& b) const;

Note the const keyword after the function. Also note that you can have both constant and non-constant functions with the same name.

The other problem, which you have in both versions, is that you expect the functions to take an argument. They don't. Instead they operate on this. So change to this:

template <typename T>
const T* Vector<T>::begin() const
{
    return &yourInternalVectorVariable[0];
}

Do the same for the end function.