Автопреобразование из std::string и обратно.
От: dosik Россия www.dosik.ru
Дата: 22.07.16 10:27
Оценка:
Сразу оговорюсь, задача не сделать variant, а читать и записывать в строку с наибольшей гибкостью и удобством необходимые пары ключ/значение.
Значения могут быть любые: строки, отдельные символы, целые , дробные, даты и т.п.
По быстрому накидал конвертор, что-то типа:
class converter {
    std::string& pvalue;
public:
    converter(std::string& val) : pvalue(val) {};

    template <typename T>
    converter& operator=(const T& val) {
        pvalue = std::to_string(val);
        return *this;
    }

    //Можно как специализации, можно просто перегрузить. Есть принципиальная разница?
    converter& operator=(const char* val) {
        pvalue = val;
        return *this;
    }

    converter& operator=(const std::string& val) {
        pvalue = val;
        return *this;
    }

    //Тут можно добавить еще необходимые преобразования

    //Ну и обратно
    operator int () { return std::stoi(pvalue); }
    operator long () { return std::stol(pvalue); }
    operator long long () { return std::stoll(pvalue); }
    operator float () { return std::stof(pvalue); }
    operator double () { return std::stod(pvalue); }
    operator long double () { return std::stold(pvalue); }
    operator unsigned long () { return std::stoul(pvalue); }
    operator unsigned long long () { return std::stoull(pvalue); }
    operator std::string () { return pvalue; }
};

Ну и для него что-то типа:
class my_map {
    std::unordered_map<std::string, std::string> values;
public:
    converter& operator [](const std::string& key) {
        converter value(values[key]);
        return value;
    }
}

Так вот на сие чудо Clang ругается: warning: reference to stack memory associated with local variable 'value' returned [-Wreturn-stack-address] (return value
Но все работает.
GCC ругается: warning: reference to local variable ‘value’ returned [-Wreturn-local-addr] (converter value(values[key])
Но на первом же обращении по индексу случается: Signal: SIGSEGV (Segmentation fault)

В принципе все верно, компилятор не гарантирует продолжительность жизни переменной после выхода из области видимости, скорее удивительно, что я додумался такую чушь написать, а Clang ее еще и съел. Но с другой стороны converter& operator [] должен вернуть временную lvalue, которая должна жить до окончания операции копирования. Или я что-то все-таки недопонимаю?

Как вариант можно рассмотреть converter как unique_ptr член класса my_map, и при каждом обращении создавать новый. Тогда он преждевременно не умрет.
Можно рассмотреть в converter вместо ссылки std::string& pvalue; указатель std::string* pvalue;, а converter как простой член класса my_map, и при каждом вызове писать в pvalue указатель на нужный индекс. Но почему-то указатели не очень жалуют в STL.

Есть еще идеи?
И все же интересно, кто из компиляторов прав?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.