Author Topic: Help writing function parameters accepting a generic list of items  (Read 3769 times)

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
In a couple of places, I am passing std::vector<LOCATION> or std::vector<map_id> into functions I write. For example:

Code: [Select]
void CreateBlastedTiles(const std::vector<LOCATION> &locs)
{
    for (LOCATION loc : locs)
    {
        CreateBlastedTile(loc);
    }
}

What I would prefer is to allow the function to accept any enumerable collection (vector, list, array, etc). This way the consumer of the function does not have to format their data into the arbitrary collection that I choose. However, I do want to constrain the function to only take collections of LOCATION.

In c#, I would use the Ienumerable interface like below:

Code: [Select]
void CreateBlastedTiles(IEnumerable<LOCATION> locs)
{
    foreach (LOCATION loc in locs)
    {
        CreateBlastedTile(loc);
    }
}

Online examples of using C++ templates are making my head spin and the book I was using doesn't cover them, since it is more of an intro to programming using C++. Some help would be appreciated, or you can tell me I just need to go buy an intermediate/advanced C++ book.

Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1269
Re: Help writing function parameters accepting a generic list of items
« Reply #1 on: March 19, 2016, 06:35:38 PM »
You could use overloads for all the collection varities, but more ideally this is where you'd want to use templates.

Code: [Select]
template <class containerT> void CreateBlastedTiles(const containerT &locs) {
  for (auto &loc: locs)
    CreateBlastedTile(loc);
}
...
std::vector<LOCATION> blah;
std::list<LOCATION> whatever;
...
CreateBlastedTiles(blah);
CreateBlastedTiles(whatever);

While I'm not sure you can directly specify what the collection element type must be without having to make specializations for every collection (which would be no better than simple overloads), that limitation will be implied by CreateBlastedTile() taking a LOCATION. On a somewhat related note, you should look up SFINAE and template specializations in general.
« Last Edit: March 19, 2016, 06:40:56 PM by Arklon »

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Re: Help writing function parameters accepting a generic list of items
« Reply #2 on: March 20, 2016, 04:38:51 AM »
I agree about just using overloads. You don't really need to be overly general most of the time. Will anyone ever try to call the function with a linked list? The array might make sense. You'll likely have to pass a size separately, since arrays don't store their size in C++. That right there already implies you'll have to write an overload anyway, even if the function is templated.

You can of course use templates and just drop the specification that it must be a collection of LOCATION objects. There will still be compile time checks that the type you pass in works for that function, it just won't have as clean of an error message. It might complain about a bad type while trying to iterate over the collection (if the loop variable is declared as LOCATION), or when trying to pass the element value as a function parameter (if the loop variable is declared with auto). Either which way, the code will only compile for a collection of LOCATION objects, or objects that can be silently converted to LOCATION objects.

Offline Vagabond

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1015
Re: Help writing function parameters accepting a generic list of items
« Reply #3 on: March 20, 2016, 01:57:27 PM »
Arklon and Hooman, thank you for the help. I'm thinking maybe function overloading instead of templates and supporting std::vector and std::array.


Offline Arklon

  • Administrator
  • Hero Member
  • *****
  • Posts: 1269
Re: Help writing function parameters accepting a generic list of items
« Reply #4 on: March 20, 2016, 09:27:42 PM »
You'll likely have to pass a size separately, since arrays don't store their size in C++.
C++11 added std::array. You'd probably still want to support regular C-style arrays, though.
« Last Edit: March 20, 2016, 09:33:29 PM by Arklon »