recipriversexclusion
recipriversexclusion

Reputation: 15356

How to pass std::map as a default constructor parameter

I haven't been able to figure this out. It's easy to create two ctors but I wanted to learn if there's an easy way to do this.

How can one pass a std::map as the default parameter to a ctor, e.g.

Foo::Foo( int arg1, int arg2, const std::map<std::string, std::string> = VAL)

I've tried 0, null, and NULL as VAL, none of the work because they are all of type int, g++ complains. What is the correct default to use here?

Or is this kind of thing not a good idea?

Upvotes: 14

Views: 17160

Answers (4)

Phidelux
Phidelux

Reputation: 2271

Since C++11 you can use aggregate initialization:

void foo(std::map<std::string, std::string> myMap = {});

Example:

#include <iostream>
#include <map>
#include <string>

void foo(std::map<std::string, std::string> myMap = {})
{
    for(auto it = std::cbegin(myMap); it != std::cend(myMap); ++it)
        std::cout << it->first << " : " << it->second << '\n';
}

int main(int, char*[])
{
    const std::map<std::string, std::string> animalKids = {
        { "antelope", "calf" }, { "ant", "antling" },
        { "baboon", "infant" }, { "bear", "cub" },
        { "bee", "larva" }, { "cat", "kitten" }
    };

    foo();
    foo(animalKids);

    return 0;
}

You can play around with this example at Godbolt.

Upvotes: 6

aschepler
aschepler

Reputation: 72271

The correct expression for VAL is std::map<std::string, std::string>(). I think that looks long and ugly, so I'd probably add a public typedef member to the class:

class Foo {
public:
  typedef std::map<std::string, std::string> map_type;
  Foo( int arg1, int arg2, const map_type = map_type() );
  // ...
};

And by the way, did you mean for the last constructor argument to be a reference? const map_type& is probably better than just const map_type.

Upvotes: 29

John Dibling
John Dibling

Reputation: 101446

First, and tangentailly, you are passing the map by const value, which is pointless and probably not what you really want. You probably want to pass by const reference, so that you don't make a copy of the map, and you ensure that your function doesn't modify the map.

Now, if you want your default parameter to be an empty map, you do it by constructing it, like so:

Foo::Foo( int arg1, int arg2, const std::map<std::string, std::string>& = std::map<std::string, std::string>())

Upvotes: 2

James McNellis
James McNellis

Reputation: 354969

You create a value-initialized temporary. For example:

Foo::Foo(int arg1,
         int arg2,
         const std::map<std::string, std::string>& the_map =
             std::map<std::string, std::string>())
{
}

(A typedef might help to make this more readable in your code)

Upvotes: 6

Related Questions