I was wondering if this was possible, and if so how I'd go about doing so. If 开发者_StackOverflowit's not possible I'll just have to add the elements during the constructor body.
Ideally I would like the map immutable after construction.
What I'm trying to achieve is adding two pairs to the map that are created from constructor parameters.
It's possible, by copy construction: invoke a function which build the map!
std::map<int,int> myFunc(int a, int b);
class MyObject
{
public:
MyObject(int a, int b): m_map(myFunc(a,b)) {}
private:
std::map<int,int> m_map;
};
Without extra tools you can only init std containers in initialization lists as far as their constructors support you. If you need more, map_list_of()
et al from Boost.Assign do a great job.
Boost.Assign in action:
class C
{
const std::map<int,int> _vi;
public:
C() : _vi(boost::assign::map_list_of(1,1)(2,1)(3,2)) {}
}
edit: updated to std::map
example.
There’s a map constructor that takes a range as a pair of iterators. Using that, you can construct something similar to your demands:
pair<int, int> init[] = { make_pair(1, 2), make_pair(2, 3) };
map<int, int> const mymap(init, init + 2);
Granted, not pretty. The next version of C++ will come with better support for initialization lists. Until then, Boost.Assign is the next best thing.
I use an initializer class:
template<class K, class V>
class MapInitializer
{
std::map<K,V> m;
public:
operator std::map<K,V>() const
{
return m;
}
MapInitializer& Add( const K& k, const V& v )
{
m[ k ] = v;
return *this;
}
};
Then to put it to use:
class C
{
const std::map<int,const char*> m_map;
public:
C() : m_map( MapInitializer<int,const char*>()
.Add( 1, "Hi there" )
.Add( 2, "In the middle" )
.Add( 9, "Goodbye" ) )
{}
};
This is free (in the sense that you aren't building a map, copying it, and throwing the first away) because of C++'s return value optimization. The same thing can be done for initializing a vector or other standard containers.
Hope that helps!
精彩评论