While inserting an element in a map of type <int,int> , we have to explicitly mention the types again as pair. Isnt is redundant?
map<int,int> m1;
//m1.insert(1,1); //NOT OK since the pair type <int,int> not mentioned
m1.insert(pair<int,int>(1,1)); //OK
m1 is declared as <int,int>. Would there be any instance wherein we try to insert any element other than <int,int> e.g. m1.insert(pair<int,string>(1,"boo")) ? If no, then isn't it redundant to write <int,int> again while inserting an element?
EDIT 1:
To explain in detail here is a small example:
template<typename T1,typename T2>
class Test
{
public:
template<typename T1>
void fun1()
{
cout<<"This is called for T1 templatized fun1"<<endl;
}
template <typename T1,typename T2>
void insert(pair<T1,T2> &obj)
{
cout<<obj.first<<" "<<obj.second<<endl;
}
};
int main()
{
Test <int,int>obj; // Even though i have declared obj as type int,int, i am still able to call insert on type int,string
obj.insert(pair<int,string>(1,"Anurag"));
Here we clearly see that the types with which i created object obj is different than the types with which i called insert() . But i dont understand how would the member function map::insert() make sure that the types are same as those with which the object is created? One way that i thought of was:
template <typename T3=T1,typename T4=T2> //where T1 and T2 are class typenames
void insert2(pair<T3,T4>& obj2)
{
cout<<"Inside insert2 \n";
}
But even this would not be allowed since this is a function template not a class template. I tried looking inside the header file of map to see the declaration of insert but got more confused.
insert is not a forwarding function. Just use brackets to initialize the pair object:
m1.insert({1, 1});
In C++11, emplace will forward the arguments.
m1.emplace(1, 1);
Or in C++03, make_pair.
Regarding your edit:
That's a pretty inaccurate representation of map. A more accurate representation would be something like this:
template <typename Key, typename T,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T>>>
struct Test
{
using value_type = std::pair<const Key, T>;
using iterator = typename std::allocator_traits<Allocator>::pointer;
std::pair<iterator, bool> insert( const value_type& value )
{
// this calls emplace
}
};
int main()
{
Test<int, int> test;
test.insert(std::pair<int, std::string>(1, "hello"));
}
Which does give a compiler error. Of course, this is why the convenience function std::make_pair was provided in the first place.
It's redundant, but that't the way it is. However, you can insert elements without having to respecify <int,int>.
This way, compiler is smart enough to figure out template arguments of the make_pair function:
m1.insert(make_pair(1,1)); // equivalent o m1.insert(make_pair<int,int>(1,1));
or that way:
m1[1] = 1;
The thing is: when you declare an template variable (pair is a type, so pair<int,int>( 1, 1 ) is a template variable declaration), template parameters must be specified. But, when you call a function (make_pair is actually a function), template parameters are optional, compiler will try to determine them and it will only complains if it fails to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With