3

For a homework assignment, I'm trying to create my own versions of std::find, std::begin, std::end, and std::size.

I've written some code that looks like this:

#include <vector>

template <typename I, typename T>
I find(const I& beg, const I& end, const T& sought)
    {/* ... */}

template <typename T, size_t S>
T* begin(T (&a)[S])
    {return &a;}

template <typename T, size_t S>
T* end(T (&a)[S])
    {return &a + S;}

template <typename T, size_t S>
constexpr size_t size(T (&)[S])
    {return S;}

int main()
{
    std::vector<int> vec = {0, 1, 2, 3};

    // ...

    // test not-found case (and `size()`)
    find(begin(vec), end(vec), size(vec));

    // ...

    return 0;
}

(size_t should implicitly convert to int)

However when I compile, clang gives off the following error:

$ clang++ -o program ./*.cpp -std=c++11 -Wall -Wextra -Wpedantic -Wconversion -Wnon-virtual-dtor
./main.cpp:##:##: error: no matching function for call to 'size'
    find(begin(vec), end(vec), size(vec)
    ^~~~
./main.cpp:##:##: note: candidate template ignored: could not match 'T [S]' against 'std::vector<int>'
constexpr size_t size(T (&)[S])
                 ^
1 error generated.

What really baffles me is that both size() and begin()/end() have the exact same template structure and parameter list, and yet the former throws a compile error while the latters don't when given the same input.

I don't think the different return type is the issue, since if it was find() would be complaining, not size().

So how is size() different from the other functions that it would throw this error with the same template structure, parameter list, and input?

dan9er
  • 369
  • 2
  • 17

1 Answers1

7

None of your begin/end/size templates match, because they only match for raw arrays (type T[S]) and not for the type you are using (std::vector<T>). You only get one error because the calls to begin and end will match the functions std::begin and std::end, due to argument dependent lookup. There is no std::size function (in C++11), so the only possible match for size is your size function which doesn't match, so you get an error.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 3
    Just to be clear, there is a [`std::size`](https://en.cppreference.com/w/cpp/iterator/size) *now*, but this question is living in the past (`-std=c++11`). If you adjust it to `-std=c++17`, the code in the question works as is. – HTNW Mar 23 '20 at 19:34