简体   繁体   中英

map insert with pair type

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> eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM