Will Beason
Will Beason

Reputation: 3551

How can I write a template to check if a given value is in an array

Per an answer to this previous question, I wrote the template below which should return true if the array contains the passed value, and false otherwise.

template <typename Type>
bool Contains(const Type container[], const Type& value) {
  return std::any_of(
      std::begin(container), std::end(container),
      [&value](const Type& contained_value) { return value == contained_value; });
}

When I try to compile, I get the following error:

error: no matching function for call to 'begin'
      std::begin(container), std::end(container),

What is causing std::begin to fail? The std::begin documentation shows it works with arrays. In this specific instance, I am instantiating the template on an enum (not an enum class).

Upvotes: 1

Views: 179

Answers (1)

Bryan Chen
Bryan Chen

Reputation: 46588

The type for Contains is wrong so that container was deduced to be const int *&, which have no override for std:begin

Error message from g++ is more clear:

main.cpp: In instantiation of ‘bool Contains(const Type*, const Type&) [with Type = int]’: main.cpp:18:34: required from here

main.cpp:9:17: error: no matching function for call to ‘begin(const int*&)’

This is fixed code. You need to pass the array as array type (int[3]) in order for std::end to figure out the length of array from the type.

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

template <typename Type, std::size_t N>
bool Contains(Type (&container)[N], const Type& value) {
  return std::any_of(
      std::begin(container), std::end(container),
      [&value](const Type& contained_value) { return value == contained_value; });
}

int main()
{
    int a[] = {1,2,3};
    int val = 1;
    int val2 = 4;
    bool result = Contains(a, val);
    bool result2 = Contains(a, val2);
    std::cout << result << std::endl;
    std::cout << result2 << std::endl;
}

Upvotes: 3

Related Questions