4

Can I overload my function to do something with a lot of arguments as in JavaScript. For example:

function f()
{
  alert(arguments[0]);
}

f(4); // will alert 4 

Can I do the same thing in C++ ?

MAT
  • 3
  • 3
davitp
  • 127
  • 2
  • 4
  • 14
  • 1
    So you want to call your function with a variable number of arguments? If that is the case you can always use variadic functions but like this page says http://en.cppreference.com/w/cpp/utility/variadic `std::initializer_list` or `variadic templates` are type safe and easier to use. – Shafik Yaghmour May 02 '13 at 11:57
  • Sorry, my example had an extra colon in it which kept it from compiling correctly. See my new edit please along with the [demo](http://ideone.com/uc3ZE5#view_edit_box). – David G May 02 '13 at 19:34

1 Answers1

9

You can use variadic template arguments and tuples:

#include <tuple>
#include <iostream>

template <class... Args>
void f(Args&&... args)
{
    auto arguments = std::make_tuple(std::forward<Args>(args)...);
    std::cout << std::get<0>(arguments);
}

void f() {} // for 0 arguments

int main()
{
    f(2, 4, 6, 8);
}

Live Demo

For bounds checking, try the following:

#include <tuple>
#include <iostream>

template <class... T>
struct input
{
    std::tuple<T...> var;
    input(T&&... t) : var(std::forward<T>(t)...) {}

    template <std::size_t N, bool in_range = 0 <= N && N < std::tuple_size<decltype(var)>::value>
    auto get() -> typename std::tuple_element<in_range ? N : 0, std::tuple<T...>>::type
    {
        return std::get<in_range ? N : 0>(var);
    }
};

template <class... Args>
void f(Args&&... args)
{
    auto arguments = input<Args...>(std::forward<Args>(args)...);

    std::cout << arguments.template get<9>();
}

void f() {} // for 0 arguments

int main()
{
    f(2, 4, 6, 8);
}

Update: If you need the first argument then you simply want a function which exposes that first argument by separating it from the parameter pack:

template<class Head, class... Tail>
void foo(Head&& head, Tail&&... tail);

If this is not satisfactory (i.e you want to get the nth-argument), you can unpack the arguments into a std::tuple<> and retrieve an element with std::get<>:

template<class... Args>
void foo(Args&&... args)
{
    auto t = std::forward_as_tuple(std::forward<Args>(args)...);
    print(std::get<5>(t));
}
David G
  • 94,763
  • 41
  • 167
  • 253
  • @shafikYaghmour Your question is a little vague. Can you narrow it down to a specific scenario? – David G May 02 '13 at 20:33
  • @ShafikYaghmour You'll need to use some form of looping to get all `N` elements. You can use a range-based for to do this: `for (auto a : tup) print( a )`. You can also use compile-time constants through template arguments. – David G May 02 '13 at 21:46
  • Is there a way to force args to be a single specific type? (Without having to abuse defaults like so: `template – Pharap Aug 11 '14 at 13:23
  • 1
    @Pharap You can use SFINAE: `template using first = T; template first::value>::type...> f(Args&&...);`. [Here's an example.](http://rextester.com/JVF56882) – David G Aug 11 '14 at 13:59
  • Thank you 1234567890, I was unable to find a decent answer for that anywhere. I was probably searching the wrong terms admittedly. SFINAE is truly the answer to all life's mysteries. – Pharap Aug 11 '14 at 14:51
  • @Pharap Glad I could help. BTW I haven't seen this answer since I wrote it last year and my code is too detailed and superfluous. I am going to update it. – David G Aug 11 '14 at 14:55
  • Unfortunately I haven't managed to get what you suggested workingin my compiler (MSVC2013). Removing the ... from the ::type... got rid of any errors, but then it accepts different types of arguments. – Pharap Aug 11 '14 at 15:59
  • @Pharap What's the error that you were originally getting? – David G Aug 11 '14 at 16:09
  • `error C3546: '...' : there are no parameter packs available to expand` on the line `first::value>::type...>`. And yes, I made sure to `#include `. – Pharap Aug 11 '14 at 16:27
  • @Pharap MSVC has incomplete C++11 support. This code runs on other modern compilers. And unfortunately I don't know a work around. – David G Aug 11 '14 at 16:30
  • I suspected as much, it doesn't have support for constexpr yet either. Though as far as I'm aware, no compiler has fully implemented the standard yet, which is a shame since the C++11 features have been a brilliant revolution. If I figure out a work around I'll come back with a comment or edit suggestion. For now I'd better stop flooding the comment box since, I was only asking on the off-chance anyway, I didn't expect to trail off into a long conversation. Thanks for the help though, it's much appreciated. – Pharap Aug 11 '14 at 16:40