С++ 14 с использованием ключевого слова auto в определении метода
У меня есть несколько std::unordered_maps
. Все они имеют std::string
как свой ключ, и их данные различаются. Я хочу сделать строку csv из заданных ключей карты, потому что эти данные должны быть отправлены по проводу подключенному клиенту. На данный момент у меня есть метод для каждой отдельной карты. Я хотел сделать это родовым, и я придумал следующее:
std::string myClass::getCollection(auto& myMap) {
std::vector <std::string> tmpVec;
for ( auto& elem : myMap) {
tmpVec.push_back(elem.first);
}
std::stringstream ss;
for ( auto& elem : tmpVec ) {
ss << elem <<',';
}
std::string result=ss.str();
result.pop_back(); //remove the last ','
return result;
}
Я компилирую с gcc 6.1.0 и -std = С++ 14 с использованием eclipse, и он компилируется, но он не связан.
Компилятор жалуется на undefined ссылку на std::__cxx11::getCollection(someMap);
Независимо от данных карты и того, как я ее называю, она всегда говорит мне:
Invalid arguments ' Candidates are: std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>> getCollection() '
Как это решить?
Ответы
Ответ 1
Как и в С++ 14 auto
параметры разрешены только в lambdas (в соответствии с комментарием @ildjarn), вы можете просто разработать шаблон функции, шаблонный по типу карты, например:
#include <sstream>
#include <string>
#include <vector>
class myClass {
...
template <typename MapType>
std::string getCollection(const MapType& myMap) {
std::vector <std::string> tmpVec;
for ( const auto& elem : myMap) {
tmpVec.push_back(elem.first);
}
std::stringstream ss;
for ( const auto& elem : tmpVec ) {
ss << elem <<',';
}
std::string result=ss.str();
result.pop_back(); //remove the last ','
return result;
}
Заметим также добавление const
для некоторой const-корректности.
Кроме того, почему бы не просто построить строку вывода напрямую с помощью объекта потока строк, не заполняя промежуточный vector<string>
(который больше кода, больше возможностей для ошибок, больше накладных расходов, меньше эффективности)?
И поскольку вы просто заинтересованы в использовании потока строк в качестве выходного потока, лучше использовать ostringstream
вместо stringstream
, поскольку он более эффективен и лучше передает ваши намерения.
#include <sstream> // for std::ostringstream
#include <string> // for std::string
...
template <typename MapType>
std::string getCollection(const MapType& myMap) {
std::ostringstream ss;
for (const auto& elem : myMap) {
ss << elem.first << ',';
}
std::string result = ss.str();
result.pop_back(); // remove the last ','
return result;
}
Ответ 2
Почему бы просто не использовать шаблон?
template <typename TMap>
std::string myClass::GetCollection(TMap &myMap) {
std::vector <std::string> tmpVec;
for ( auto& elem : myMap) {
tmpVec.push_back(elem.first);
}
std::stringstream ss;
for ( auto& elem : tmpVec ) {
ss << elem <<',';
}
std::string result=ss.str();
result.pop_back(); //remove the last ','
return result;
}
Ваш метод точно такой же, но вместо ключевого слова auto
мы используем синтаксис функции шаблона для обработки вывода типа.
Ответ 3
auto
параметры разрешены только в lambdas в С++ 14.
Вероятно, это потому, что в классической функции, такой как ваша, вы могли бы объявить шаблон функции (что в основном происходит в случае лямбда), в то время как lambdas не может быть шаблонами.