2013-09-01 3 views
1

Я пытаюсь вернуть содержимое std::pair, которое имеет int и string значения. Какой тип возврата для функции следует сохранить?Как вернуть содержимое std :: pair?

Я пробовал с int и тип возврата, но дает ошибку для обоих. Я дал ошибку ниже:

#include<iostream> 
#include<algorithm> 
#include<map> 
#include<vector> 

    std::pair<int,std::string>client() 
{ 

std::vector<std::string> most { "lion","tiger","kangaroo", 
           "donkey","lion","tiger", 
           "lion","donkey","tiger" 
           }; 
std::map<std::string, int> src; 
for(auto x:most) 
    ++src[x]; 

std::multimap<int,std::string,std::greater<int> > dst; 

std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), 
        [] (const std::pair<std::string,int> &p) { 
        return std::pair<int,std::string>(p.second, p.first); 
        } 
       ); 

std::multimap<int,std::string>::iterator it = dst.begin(); 

for(int count = 0;count<3 && it !=dst.end();++it,++count) 
    std::cout<<it->second<<":"<<it->first<<std::endl; 

return *it; 
} 

int main() 
{ 
std::multimap<int,std::string>::const_iterator rec; 
rec= client(); // Error no match for ‘operator=’ in ‘rec = client()()’ 
std::multimap<int,std::string>::iterator it = rec.begin(); //error: ‘std::multimap<int, std::basic_string<char> >::const_iterator’ has no member named ‘begin’ 

for(int count = 0;count<3 && rec !=it.end();++it,++count) // error: has no member named 'end' 
    std::cout<<rec->second<<":"<<rec->first<<std::endl; 

} 
+3

Erm, верните пару себя? – jrok

+1

'std :: pair client()'? – Jarod42

+1

Если у вас есть C++ 11, используйте ключевое слово auto. –

ответ

7

Просто вернуть пару int & std::string сам как multimap содержит, что в качестве элемента

std::pair<int,std::string> client(){ 
//... 
} 
+0

до тех пор, пока он не даст длинное сообщение об ошибке, я не мог понять, где ошибка! – user123

+0

@ Каримхан, вам нужно вставить элемент, а не назначить его. – chris

+1

@Karimkhan Я думаю, что вы взяли мой код из [здесь] (http://stackoverflow.com/a/18547612/1870232) Итак, если вы хотите вернуть итератор в первый элемент, вам нужно использовать 'std :: multimap :: iterator client() {... return it;} ' Также в заголовке вопроса это не задано: P – P0W

1

Если вы хотите, чтобы вернуть запись на карту (то есть, как ключ и значение), то просто используйте std::pair<int, std::string> в качестве возвращаемого типа, как упоминалось в других ответах.

Если вы хотите просто вернуть ключ, верните it->first (и используйте int в качестве возвращаемого типа). Если вы хотите вернуть только значение, верните it->second (и используйте std::string в качестве возвращаемого типа).

+0

, пока он не даст длинное сообщение об ошибке, я не мог понять, где ошибка! – user123

1

Если вы хотите вернуть значение из std::map, я бы не использовал явно std::pair (хотя для этого все в порядке). Лично я бы использовал std::map::value_type, который представляет тип значений, хранящихся на карте (обратите внимание: все контейнеры имеют член типа, называемый value_type, который представляет сохраненный тип).

std::multimap<int,std::string>::value_type client() 
{ 
    // STUFF 
    std::multimap<int,std::string>::iterator it = dst.begin(); 

    // STUFF; 
    return *it; // Note: this is UB if it == dst.end() 
} 

Поэтому я хотел бы использовать value_type, а не std::pair, как правило, я бы не использовать явные типы, но было бы создано определений типов (так это выглядит).

typedef std::multimap<int,std::string> MapForX; // Modification to map here 
               // Will automatically roll threw all 
               // the following code as everything 
               // is defined in terms of `MapForX` 

MapForX::value_type client() 
{ 
    // STUFF 
    MapForX::iterator it = dst.begin(); 

    // STUFF; 
    return *it; // Note: this is UB if it == dst.end() 
} 

Теперь, если я изменю тип MapForX. Тогда мне нужно только изменить одну вещь (единственный typedef). Если вы вернетесь std::pair<int,std::string>, вам необходимо внести изменения в два места (typedef и возвращаемое значение). Для меня это избыточное изменение, которое может вызвать проблемы.

В демо: Если вы возвращаете std::pair<int, std::string> ваш код выглядит следующим образом:

typedef std::multimap<int,std::string> MapForX; // Modification to map here 
               // Will automatically roll threw MOST 
               // the following code. 

// But notice this return type is not defined in terms of MapForX 
// Thus if you change MapForX you will also need to change the return type. 
// to match the correct type. 
std::pair<int, std::string> client() 
{ 
    // STUFF 
    MapForX::iterator it = dst.begin(); 

    // STUFF; 
    return *it; // Note: this is UB if it == dst.end() 
} 

Это работает отлично. Но в будущем вы должны внести некоторые изменения. И вы также меняете тип карты int => MySpecialType. Теперь в моем втором примере (с typedef) вам нужно только сделать одно изменение (в MapForX). В приведенном выше примере вам нужно сделать два изменения (один для MapForX и один std :: pair для возвращаемого типа).

+0

спасибо, приятное объяснение. но я не мог понять, зачем нужен второй код? – user123

+1

@ Каримхан: Его не нужно. Но для упрощения чтения и обновления кода иногда бывает проще вводить типы typedef. Вопрос в том, как вы думаете, что это облегчает чтение. Если вы это сделаете, используйте typedef. Если вы этого не сделаете, используйте полное имя. Это личное предпочтение читаемости. Но по мере того как ваши типы становятся более сложными, этот метод пригодится. –

+0

Да, Гор это сейчас! – user123

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