Search code examples
c++std-pair

How to use std::pair with classes?


so I'm experimenting with cvc5 and just wanted to keep track of the Terms in a map so I have created this:

std::map<std::string, std::pair<Term, int>> terms;

Basically, for I used the name as an index and I store the Term with other info in the map.

I have created a subtype of Term called TermStruct and I wanted to create another similar map:

std::map<std::string, std::pair<TermStruct, int>> termsStructs;

TermStruct was created roughly in the following way

class  TermStruct : public Term {
public:
    TermStruct(Term *t) : Term() {
        this->t = t;
    }
    
    bool isNull();
    Term *getTerm() { return this->t; };
    
    std::string toString();
    
private:
    
    Term *t = nullptr;

};

Now when I tried to add a new element to the termStructs map in the following way:

termsStructs[str] = std::pair(term, offset);

Note: term is of the correct type.

I have a number of compilation error such as:

/usr/include/c++/11/bits/stl_map.h:501:37:   required from ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::pair<TermStruct, int>; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::pair<TermStruct, int> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::pair<TermStruct, int>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
/home/alberto/progetti/llvm/plugin/runtime/cvc5/Runtime.cpp:113:25:   required from here
/usr/include/c++/11/tuple:1824:9: error: no matching function for call to ‘std::pair<TermStruct, int>::pair()’
 1824 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)

Any idea why and how to fix it?

Thanks


Solution

  • pair has nothing to do with this problem. It is all about map. I see two options.

    1. Introduce a default constructor(a constructor without parameters) for TermStruct if you want to use std::map::operator[]. Here's why:
      • termsStructs[str] = std::pair(term, offset) does not insert the pair object right away
      • termsStructs[str] first creates a new key-value pair and adds it to the map(if there is no entry for str)
      • It is done by running std::make_pair(key, T())
      • As T here is std::pair, it tries to call Term() (FYI the second(integer) is zero-initialized)
      • However there is no Term() defined - compiler error

    You may refer these links for details.

    https://en.cppreference.com/w/cpp/container/map/operator_at (1) https://en.cppreference.com/w/cpp/utility/pair/pair (1)

    1. Or you can use emplace or insert.

    These methods look uglier than the above but they behave just like what you must have expected. It does not require a default constructor.

    For example,

    termsStructs.emplace(str, std::pair(term, offset));
    termsStructs.insert({str, std::pair(term, offset)});