Using a user-defined type as map value in c++
Is it possible to instantiate an object like this
Yes, it is.
or do i have to use the new operator in some way?
No, you don't.
How can i make this work?
That already works, assuming you define the variables and types that were missing from the example:
#include <map>
#include <utility>
using std::map;
using std::make_pair;
struct Type {
Type(int,int,int){}
Type(){}
void useMemberFunction(){}
};
int main() {
int keyVal = 0, intVal = 0;
map<int,Type> myMap;
myMap.insert(make_pair(keyVal,Type(intVal,intVal,intVal))); //Type takes 3 int-values for construction.
myMap[intVal].useMemberFunction();
}
One note though: As per documentation, std::map::operator[]
requires that the value type is default constructible. If the type is not default constructible, then you cannot use the subscript operator. You can use std::map::at
or std::map::find
instead.
C++ std::map with user defined data type
Because in the statement
forest[i]=Set(i);
the forest[i]
will try create a Set
object using the default constructor and placed in that location. Then another will be created using Set(i)
and will be assigned to the ith position using assignment operator. hence you have to provide a default constructor.
To avoid it use std::map::insert
method.
forest.insert( {i, Set(i)} );
What requirements must std::map key classes meet to be valid keys?
All that is required of the key is that it be copiable and assignable.
The ordering within the map is defined by the third argument to the
template (and the argument to the constructor, if used). This
defaults to std::less<KeyType>
, which defaults to the <
operator,
but there's no requirement to use the defaults. Just write a comparison
operator (preferably as a functional object):
struct CmpMyType
{
bool operator()( MyType const& lhs, MyType const& rhs ) const
{
// ...
}
};
Note that it must define a strict ordering, i.e. if CmpMyType()( a, b
returns true, then
)CmpMyType()( b, a )
must return false, and if
both return false, the elements are considered equal (members of the
same equivalence class).
Can we use a user defined class for the key in a STL map?
Any type can be used as a key as long as it is
- Copyable
- Assignable
- Comparable, since the map is sorted by key
If your class is just a simple structure, then it's already copyable and assignable. For a class to be comparable, you must either implement operator<
, or create the map with a custom comparison function to use instead.
The only impact on time efficiency comes from larger objects taking longer to copy and compare. If the objects need to be that size, then there's nothing you can do about that, so don't worry about it.
Overload std::map with different key type
What you need is called heterogeneous lookup and supported by std::map
since C++14. For that you can define your own comparator structure and provide type is_transparent
in it to enable this functionality. Details on how to enable heterogeneous lookup can be found here How can I search an std::map using a key of a different type
Also note, while std::map::find()
does support it std::map::operator[]
does not, so you have to replace your code:
if (index.find("test") != index.end())
{
index["test"].push_back(0);
}
to something like:
auto it = index.find("test");
if( it != index.end())
it->second.push_back(0);
and you should do that anyway, as you would do two lookups instead of one otherwise and that is significantly expensive operation on map.
So for your case comparator should be something like:
struct CompareType
{
using is_transparent = std::true_type;
// standard comparison (between two instances of Type)
bool operator()(const Type& lhs, const Type& rhs) const { return lhs.key < rhs.key; }
// comparisons btw Type and std::string
bool operator()( const Type& lhs, const std::string &rhs) const { return lhs.key < rhs; }
bool operator()(const std::string &lhs, const Type& rhs) const { return lhs < rhs.key; }
};
then you create your map by:
std::map<Type, std::vector<int>,CompareType> index;
and you do not need comparison methods in Type
itself anymore
Another way is to submit std::less<>
as third parameter to std::map
, but in that case you are missing the comparison operator, that takes std::string
as left operand and Type
as right and as that comparison operator cannot be member of Type
I think it is cleaner to do it through a separate comparator (code there is consistent).
Using find in map with user defined class as key
std::map
is using the relational operator <
for ordering and checking key uniqueness. Since your implementations of operator<
use the a
member only for comparing it will ignore b
when evaluating key equality. operator==
is not used from the map interface - it is replaced by !(a < b || b < a)
. You need something like
bool Entry::operator<(const Entry& e){
return a < e.a || a == e.a && b < e.b;
}
You could remove operator>
and operator==
or keep them if you need them for other purposes.
Related Topics
Visual Studio Code: Take Input from User
How to Print Current Time (With Milliseconds) Using C++/C++11
Most Efficient Way to Compare a Variable to Multiple Values
How to Fully Disable Resizing a Window Including the Resize Icon When the Mouse Hovers the Border
Countdown Until Matching Digits
Forcing the Qt Gui to Update Before Entering a Separate Function
What Is an Undefined Reference/Unresolved External Symbol Error and How to Fix It
Why Is Iostream::Eof Inside a Loop Condition (I.E. 'While (!Stream.Eof())') Considered Wrong
Can a Local Variable'S Memory Be Accessed Outside Its Scope
Why Do I Get the Same Sequence For Every Run With Std::Random_Device With Mingw Gcc4.8.1
Where Are Static Variables Stored in C and C++
How to Get Assembler Output from C/C++ Source in Gcc
Calling C++ Member Functions Via a Function Pointer
Why Can't I Make a Vector of References
What Will Happen When I Call a Member Function on a Null Object Pointer