C++ List of Pairs

34,864

Solution 1

Class std::basic_string has no constructor that has one parameter of type char.So these statemenets are invalid

  freq2.push_back(std::make_pair(*it,0)); //ERR:No instance of fn matches arg list 
  freq2.push_back(std::make_pair('S',0)); //ERR:No instance of fn matches arg list

Speaking more precisely in these statements there is an attempt to build an object of type std::pair<std::string, int> from an object of type std::pair<char, int>. This requires that there would be a constructor of class std::string that has parameter of type char. However there is no such a constructor.

As for these statements

  freq[0] = std::make_pair(*it,0);        //This is fine
  freq[0] = std::make_pair('S',0);        //This is fine

then there is used an assignment operator of class std::basic_string. The class has an overloaded assignment operator that accepts an object of type char.

basic_string& operator=(charT c);

So these statements are correct.

Consider the following example

#include <iostream>
#include <string>
#include <utility>

int main() 
{
    std::pair<std::string, int> p1 = { "a", 1 };
    std::pair<char, int> p2 = { 'B', 2 };

    p1 = p2;

    std::cout << p1.first << '\t' << p1.second << std::endl;

    return 0;
}

The output is

B   2

As class std::pair has a template assignment operator and class std::string in turn has assignment operator that has parameter of type char then this code is compiled successfully.

If you would write for example

std::pair<std::string, int> p1 = std::make_pair( 'a', 1 );

instead of

    std::pair<std::string, int> p1 = { "a", 1 };

you would get an error because there is no conversion from std::pair<char, int> to std::pair<std::string, int> because there is no constructor from char to std::string.

Solution 2

There is no implicit constructor in std::string that accepts char and can be used to convert type char to std::string. What you can use is this constructor:

basic_string( size_type count, CharT ch, const Allocator& alloc = Allocator() );

so

freq2.push_back(std::make_pair( std::string( 1, *it ),0));

and so on

Solution 3

The issue is that you're attempting to construct a std::string from a single char. There is no such constructor for std::string.

Share:
34,864
Admin
Author by

Admin

Updated on July 14, 2022

Comments

  • Admin
    Admin almost 2 years

    While getting comfortable with the C++ STL I ran into this issue using a list of pair objects.

    int count (std::string input, std::vector<std::string> screen){
    
      std::string::iterator it = input.begin();
    
      std::pair<std::string, int> freq[10];
      std::list<std::pair<std::string,int>  > freq2;
    
      freq2.push_back(std::make_pair(*it,0)); //ERR:No instance of fn matches arg list 
      freq2.push_back(std::make_pair('S',0)); //ERR:No instance of fn matches arg list
      freq2.push_back(std::make_pair("S",0)); //This is fine
    
      freq[0] = std::make_pair(*it,0);        //This is fine
      freq[0] = std::make_pair("S",0);        //This is fine
      freq[0] = std::make_pair('S',0);        //This is fine
    
      return 1;
    
    }
    

    Both freq and freq2 are quite similar except freq2 is just a list. Freq is able to accept chars, strings, and the iterator pointer and both pairs (freq,freq2) are declared as pairs. Not sure why this is happening, any tips? Thanks.

    edit: It makes a lot more sense now, all the responses I got were really helpful, thank you guys!

  • dyp
    dyp almost 10 years
    @YZ.learner Because, for some reason, there is an assignment-operator that accepts a single character on the rhs.
  • Bill Lynch
    Bill Lynch almost 10 years
    To elaborate, the call in freq2 is using constructors. The call in freq is using the default constructor and then the assignment operator.
  • GuLearn
    GuLearn almost 10 years
    @dyp There is no "signle character" on the rhs. make_pair returns a std::pair
  • Bill Lynch
    Bill Lynch almost 10 years
    @YZ.learner: Internally, the pair will use operator= when making the assignment.
  • Bill Lynch
    Bill Lynch almost 10 years
    @YZ.learner: Note the difference between: std::pair<std::string, int> fails('S', 0); and std::pair<std::string, int> works; works = std::make_pair('S', 0);.
  • GuLearn
    GuLearn almost 10 years
    @sharth, Well, I guess my question then would be why can you assign an object of type std::pair<std::string, int> to a value of type std::pair<char, int>
  • David Tr
    David Tr almost 10 years
    But for the second set of statements, doesn't std::make_pair have to construct the object first before it will be reassigned to the pair in freq?
  • Bill Lynch
    Bill Lynch almost 10 years
    @YZ.learner: Because it has an assignment operator that looks like this: std::pair<T1, T2> = std::pair<U1, U2>, the lhs and rhs don't have to be the same types. We just require that we can do T1 = U1 and T2 = U2.
  • fjardon
    fjardon almost 10 years
    Please add this to your answer. +1
  • Vlad from Moscow
    Vlad from Moscow almost 10 years
    @David Tr It constructs an object of type std::pair<char, int>.
  • David Tr
    David Tr almost 10 years
    Oh that makes perfect sense now, your example after the fact made sense. I didn't know the assignment operator worked like that on a pair object. Good explanation.
  • Admin
    Admin almost 10 years
    I like that explanation @sharth