2014-07-17 8 views
3

Получив удобство с C++ STL, я столкнулся с этой проблемой, используя список парных объектов.C++ Список пар

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; 

} 

Как freq, так и freq2 очень похожи, кроме freq2 - это всего лишь список. Freq может принимать символы, строки и указатель итератора, и обе пары (freq, freq2) объявляются как пары. Не знаете, почему это происходит, какие-нибудь советы? Благодарю.

Редактировать: Теперь это намного больше смысла, все ответы, которые я получил, были действительно полезны, спасибо вам, ребята!

+0

какой компилятор вы используете ......... я получаю другой набор ошибок –

+0

Использование VC++ 11 –

ответ

3

Класс std::basic_string не имеет конструктора, который имеет один параметр типа char .so эти statemenets недействительны

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 

Говоря более точно, в этих заявлениях есть попытка построить объект типа std::pair<std::string, int> из объекта тип std::pair<char, int>. Это требует, чтобы был конструктор класса std::string, который имеет параметр типа char. Однако такого конструктора нет.

Что касается этих заявлений

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

то используется оператор присваивания класса std::basic_string. Класс имеет перегруженный оператор присваивания, который принимает объект типа char.

basic_string& operator=(charT c); 

Таким образом, эти утверждения верны.

Рассмотрим следующий пример

#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; 
} 

Выход

B 2 

В классе std::pair имеет оператор присваивания шаблона и класс std::string в свою очередь, оператор присваивания, который имеет параметр типа полукокса, то этот код успешно скомпилирован.

Если бы написать, например

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

вместо

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

вы получите ошибку, потому что нет никакого преобразования из std::pair<char, int> в std::pair<std::string, int>, потому что нет конструктора от char к std::string.

+1

Но для второго набора операторов не std :: make_pair должен сначала построить объект, прежде чем он будет переназначен на пару по частоте? –

+1

@David Tr Он строит объект типа std :: pair . –

+0

О, это имеет смысл теперь, ваш пример после того, как факт имеет смысл. Я не знал, что оператор присваивания работал на парном объекте. Хорошее объяснение. –

4

Там нет неявного конструктора в std::string, который принимает char и может быть использован для преобразования типа char в std::string. То, что вы можете использовать этот конструктор:

basic_string (количество size_type, ДИАГРАММА ч, Const Allocator & Alloc = Распределитель());

так

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

и так далее

+1

Но почему все три задания на 'freq' работают? – GuLearn

+1

@ YZ.learner Поскольку по какой-то причине существует оператор присваивания, который принимает единственный символ в rhs. – dyp

+0

Чтобы разработать, вызов в 'freq2' использует конструкторы. Вызов в 'freq' использует конструктор по умолчанию, а затем оператор присваивания. –

0

Вопрос заключается в том, что вы пытаетесь построить std::string из одного гольца. Нет такого конструктора для std::string.

1

Кажется, что вы смешиваете символы char и std :: string. Итераторы строк указывают на отдельные значения символов, а не на std :: string. Отзыв http://www.cplusplus.com/reference/string/string/begin/ для деталей.

Кроме того, 'S' НЕ equivilent чтобы "S" как первый имеет тип полукокса в то время как второй является тип символ *, который указывает на адрес в памяти, который содержит 'S' с последующим '\0' (в «нулевой символ», который НЕ то же самое, что и null).

freq2.push_back(std::make_pair(*it,0)); //The iterator is pointing to a literal character value, and not a string 
freq2.push_back(std::make_pair('S',0)); //This is a literal character, and not a string literal 
freq2.push_back(std::make_pair("S",0)); //This is fine and what you intended 

Назначения массиву делают это посредством неявного преобразования. См. http://www.cplusplus.com/reference/utility/make_pair/.

freq[0] = std::make_pair(*it,0);  //Implicit conversion from Pair<char, int> 
freq[0] = std::make_pair("S",0);  //Implicit conversion from Pair<char*, int> 
freq[0] = std::make_pair('S',0);  //Implicit conversion from Pair<char, int> 

потенциал работа вокруг, если вы на самом деле нужно эта функция преобразования будет создать переменную типа std::pair<std::string, int>, а затем толкая значение на список. Я бы рекомендовал это только в отчаянном и странном случае, а вместо этого правильно исправить намерение кода.

Смежные вопросы