Pier
Pier

Reputation: 10817

Pass an object as parameters to a function in C++

In Javascript or ActionScript it's possible to pass an object to a function or a constructor.

myfunction({myParam:1, myOtherParam:"hello"});

It is very useful when you have a lot of parameters to pass, IMO it makes using functions easier than using the classic approach.

myFunction(1,"hello");

Is there something similar in C++?

TIA

Upvotes: 0

Views: 248

Answers (8)

Gigi
Gigi

Reputation: 4962

boost parameter http://www.boost.org/doc/libs/release/libs/parameter/ do exactly what you want.

From its abstract:

Use this library to write functions and class templates that can accept arguments by name

Small example:

// include boost parameter
#include <boost/parameter/keyword.hpp>
namespace parameter = boost::parameter;

// first declare named parameters
BOOST_PARAMETER_NAME(a)      // Note: no semicolon
BOOST_PARAMETER_NAME(b)

// then declare your function
BOOST_PARAMETER_FUNCTION(
      (int),                 // 1. parenthesized return type
      my_function,           // 2. name of the function
      tag,                   // 3. namespace of tag types (don't change!)
      (required (a, int) )   // 4. one required parameter of type int
      (optional              //    and an optional parameters, with default value
        (b, int, 0)
      )
)
{
  return a + b;
}

// then you can call it with no named parameters
int result = my_function(1, 2);

// or with named parameters
int result = my_function(_a=1, _b=2);

// also with optional parameters omitted
int result = my_function(_a=3);

Upvotes: 4

bitmask
bitmask

Reputation: 34628

You can do the following, which supports default values to a limited amount (limited by the template system of C++). You will need to compile this with the newest standard (C++11)

// used to skip arguments and default to the previously specified value
struct UseDefault {
  // empty intentionally!
};

// using this is optional, and only required if you want to provide default values by the CALLED function
template <typename T, T def> struct Default {
  T value;
  operator T() {
    return value;
  }
  Default(T value) : value(value) {}
  Default(UseDefault ignore) : value(def) {(void)ignore;}
};

// using tuple, you can bundle any number of parameters to one
int myFunc(std::tuple<Default<int,7>,Default<char,'x'>,std::string> parameters) {
  std::cout << std::get<0>(parameters) << ", " << std::get<1>(parameters) << std::endl;
  return 0;
}

You can then invoke myFunc like this:

func(std::make_tuple(6,UseDefault(),"hi"));

Note however, that there are some limitation to the template parameter types, for instance, you cannot pass strings (or char*s for that matter) as template parameters. However, if you only need reasonable basic default values, this could work.

Of course if you drop your requirement to specify default values, you can simply use the std::tuple without my Default type.

Upvotes: 0

Guy Sirton
Guy Sirton

Reputation: 8401

You can use the "named parameter idiom": http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20

Which would make your call look like:

f(1).myOtherParam("Hello")

See here for a comparison with Boost parameter.

Upvotes: 1

stinky472
stinky472

Reputation: 6797

Not at the language level, but:

It is very useful when you have a lot of parameters to pass, IMO it makes using functions easier than using the classic approach.

You should really consider cutting down on your parameters if you can. Often this can be achieved by using aggregates:

Example: 
    draw_rectangle(x1, y1, x2, y2, r, g, b, a)
Could be reduced to:
    draw_rectangle(p1, p2, color)
Or even further:
    draw_rectangle(rect, color)

The temptation for named parameters should be mitigated considerably if you do this.

You can also use alternative approaches like Boost Parameter which, through a lot of template magic, accomplishes something like this. However, it requires you turn all your functions using this technique into templates written in a very precise way, and it's a very bulky and heavy-handed attempt to force the language to do something it wasn't designed to do if you ask me.

Upvotes: 0

wallacer
wallacer

Reputation: 13213

Use structs or classes to group your data.

If you're looking for a way to pass key value pairs, use STL maps

Upvotes: 0

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81684

No, not really. There is a map class in the standard library, and of course you could write a function that accepted a map full of named values as input, but there's nothing that exists directly as a language feature equivalent to what you've shown.

As several other posters have pointed out, of course you can define a class to hold all the data values, but this just pushes the ordered parameter list from the function to the constructor of that object, so it buys you nothing at all.

Upvotes: 0

Borealid
Borealid

Reputation: 98469

Yes.

In C++, an object is an instance of a class. You could create a class holding all the possible arguments, instantiate it and fill it with your particular values, and then pass that instance to the function.

You cannot just pass an arbitrary object instead of the function's arguments, because C++ doesn't have named arguments - only the position matters, and the position within some kind of hash structure is lost. So you can't say foo(y=3) when you have a function foo(int x, int y) because the names x and y only have meaning within the function - not to its callers.

Upvotes: 0

Alexander Gessler
Alexander Gessler

Reputation: 46607

One could use structures:

struct foo {
   int a,b,c;
   float f;
}

Sadly, you need to define them somewhere and the receiving function needs to accept them, you can't just make them up in-place.

At the end of the day, there's no language tool in C++ that could mimic the JavaScript 'idiom'. Such stuff lies in the nature of a dynamic language, which C++ is not.

Upvotes: 0

Related Questions