2

I am trying to implement a function that can take an arbitrary number of std::size_t variables and use them accordingly.

I wish to be able to call the function (let's call it Foo for the sake of argument) as follows:

Foo( some_other_type, 1, 2, 5, 7, 10 );

I tried the following:

template <typename T, std::size_t... Coords>
T Foo( T tSomething, Coords... coords );

But that doesn't work, and if I removed the last parameter so it was valid C++ syntax, I would have to call it as follows Foo<1, 2, 5, 7, 10>( some_other_type ); Which is not what I wanted.

I could use variadic arguments:

template <typename T>
T Foo( T tSomething, ... );

But then I would lose the type-safety that I am looking for. So my question is, is there a way in C++11 aside from say using std::initializer_list<std::size_t>, which would then require me to call Foo as follows:

Foo( some_other_type, {1, 2, 5, 7, 10} );

And would mean I couldn't unpack the arguments to construct another type.


EDIT: The reason I wish to have something similar to variadic templates and why std::initializer_list or a recursive version of Foo won't work, is say I have a class Bar whose constructor requires a variable number of arguments depending on the specific instantiation, I wish to do something similar to the following:

template <typename T, std::size_t... Coords>
T Foo( T tSomething /*, Coords... coords*/ )
{
    Bar<sizeof...(Coords)> bar( /*coords...*/ Coords... );
    // Do stuff...
    return bar.tProperty;
}

But I wish to be able to call Foo as stated above rather than with a template list.

Constructor
  • 7,273
  • 2
  • 24
  • 66
Thomas Russell
  • 5,870
  • 4
  • 33
  • 68
  • 2
    @nosid I've updated my question to explain why this isn't a duplicate of that question. – Thomas Russell Jul 13 '14 at 11:43
  • @Shaktal Then it's a duplicate of http://stackoverflow.com/q/3703658 or one of the probably dozens of similar questions (which shows that we need better language support IMO). – dyp Jul 13 '14 at 11:52
  • See [this](http://stackoverflow.com/a/24654191/1609356). Is my answer to a near identical question. My answer explains how to achieve uniform typing via a compile-time predicate and `static_assert()` for a useful error message. – Manu343726 Jul 13 '14 at 11:59

1 Answers1

0

I found the solution to this a bit counter-intuitive at first. You need a "typename... Coords", instead of declaring it as size_t. This is because you want the compiler to fill in the typename.

You can ensure type safety by forcing this to be used as a size_t.

template <typename T, typename... Coords>
T Foo( T tSomething, const Coords... coords )
{
    std::array<size_t, sizeof...(Coords)>unpacked_coords {coords...};
    for (size_t coord : unpacked_coords)
    {
        // do stuff
    }
    return tSomething;

}

You can now call like:

Foo( some_other_type, 1, 2, 5, 7, 10 );

As you wanted :)

Michael Gazonda
  • 2,720
  • 1
  • 17
  • 33