Конвейер из Istringstream в шаблоны

У меня есть следующие вопросы: У меня есть карта от string до string, которая называется psMap. т.е. psMap["a"]="20", psMap["b"]="test", psMap["c"]="12.5", psMap["d"]="1" (true) поэтому на карте хранятся строковые выражения различных типов базовых данных.

Следующая функция foo должна (с учетом ключа) скопировать сопоставленное значение в переменную соответствующего типа, т.е.

int aa;
foo("a", aa); 
=> aa=20.

В явном виде я хочу иметь одну функцию для всех возможных типов данных (поэтому без ручного приведения), поэтому я попытался использовать шаблоны, использующие автоматическое преобразование istringsteram, а именно

template<class PARAMTYPE>
void foo(string _name, PARAMTYPE& _dataType) {
    PARAMTYPE buff;
    istringstream(psMap[_name]) >> buff;
    _dataType = buff;
}

Проблема в том, что операция ">>" выдает ошибку: Error: no match for »operator>>« in »std::basic_stringstream<char>((* ....

Что здесь происходит не так? stringstream не распознает правильный тип данных и пытается передать абстрактный тип «шаблона»? Как я могу заставить мой код работать?

Спасибо за ваши старания :)


person Martin    schedule 31.01.2014    source источник
comment
Разыменуйте его в >> *buf и *_dataType = *buff;.   -  person Me myself and I    schedule 31.01.2014
comment
Разве вам не нужен istringstream, а не stringstream?   -  person parkydr    schedule 31.01.2014
comment
Кстати, buff кажется бесполезным, используйте dataType напрямую.   -  person Jarod42    schedule 31.01.2014
comment
@ parkydr: извините, исправил   -  person Martin    schedule 31.01.2014


Ответы (3)


Вы создали временную std::istream, что означает, что она не может привязываться к неконстантной ссылке. Некоторые из >> являются функциями-членами, и они будут работать, но другие являются бесплатными функциями с сигнатурой:

std::istream& operator>>( std::istream&, TargetType& );

и они не будут работать (или даже компилироваться).

Чтобы избежать проблемы, либо просто объявите std::istringstream и используйте его, либо вызовите функцию-член для временного объекта, которая ничего не делает, но возвращает (неконстантную) ссылку:

std::istringstream( psMap[name] ).ignore(0) >> buff;

(Лично я нахожу отдельную переменную более читаемой.)

person James Kanze    schedule 31.01.2014
comment
Для обеих версий я получаю ошибку из-за неоднозначной перегрузки для оператора ›› - person Martin; 31.01.2014
comment
@Мартин Для чего PARAMTYPE? - person James Kanze; 31.01.2014

Вы используете ссылку в качестве аргумента шаблона, поэтому, если вы вызываете

foo("a", aa);

без '& все должно быть в порядке (требовался способ, которым вы пробовали оператор >> для указателя). Вам также необходимо изменить последнюю строку шаблона:

_dataType = buff;
person Wojtek Surowka    schedule 31.01.2014

Попробуйте эту реализацию:

template<class R>
R get_value(const std::string& name) {
    R result{};
    std::istringstream buffer{psMap[name]};
    buffer >> result;
    return result;
}

код клиента:

int x  = get_value<int>("a");

Также не используйте идентификаторы, начинающиеся со знака подчеркивания. Это зарезервировано для разработчиков библиотек.

person utnapistim    schedule 31.01.2014
comment
Идентификаторы, начинающиеся с подчеркивания: нет. Идентификаторы, начинающиеся со знака подчеркивания, за которым следует нижний регистр, зарезервированы только в глобальном масштабе. По крайней мере, не в теории; на практике у меня тоже были проблемы. (Но, конечно, вы никогда не должны начинать или переменную с символа подчеркивания из соображений удобочитаемости.) - person James Kanze; 31.01.2014
comment
Обычно я заканчиваю частные переменные знаком подчеркивания. Я нахожу их читаемыми, и до сих пор у меня не было проблем (name_, value_, fragments_ и т. д.). - person utnapistim; 31.01.2014
comment
Это зависит от шрифта, но при большом количестве шрифтов подчеркивание исчезает. Как правило, использование символа подчеркивания в начале или в конце очень недружелюбно по отношению к вашим читателям. - person James Kanze; 31.01.2014
comment
Я даже не рассматривал проблему исчезающего подчеркивания. Я подумаю об альтернативе своему личному соглашению о кодировании :( ... Спасибо. - person utnapistim; 31.01.2014
comment
Я получаю сообщение об ошибке при инициализации результата R{}; строка: результат должен быть инициализирован конструктором, а не {...} - person Martin; 31.01.2014
comment
Если вы используете С++ 11, он должен работать (если у вас есть конструктор по умолчанию или R является типом POD). Если вы не используете компилятор C++11, замените строку на R result = R(); (для которой по-прежнему требуется конструктор по умолчанию или тип POD). - person utnapistim; 31.01.2014
comment
добавил -std=c++0x и эта строка проходит. Однако я получаю ту же ошибку, что и выше: неоднозначная перегрузка оператора ›› - person Martin; 31.01.2014
comment
Можете ли вы написать только код std::istringstream buffer{psMap[name]}; buffer >> result; без функции? Если вы не можете, возможно, вы пытаетесь прочитать значение, для которого не определено >>. - person utnapistim; 31.01.2014