У меня есть несколько 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 = c ++ 14, используя eclipse, и он компилируется, но не связывается.
Компоновщик жалуется на неопределенную ссылку на std::__cxx11::getCollection(someMap);
Независимо от картографических данных и от того, как я их называю, это всегда говорит мне:
Invalid arguments ' Candidates are: std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>> getCollection() '
Как мне это решить?
Как в C ++ 14 auto
параметры разрешены только в лямбдах (согласно комментарию @ 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;
}
Почему бы просто не использовать шаблон?
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
ключевое слово, мы используем синтаксис функции шаблона для обработки вывода типа.
auto
параметры разрешено только в лямбдах в C ++ 14.
Вероятно, это связано с тем, что в классической функции, подобной вашей, вы могли бы объявить шаблон функции (что, в основном, и происходит в случае лямбды), в то время как лямбды не могут быть шаблонами.