Возможно ли установить конструктору по умолчанию значения `std::map`?

#c #stl #map #std

#c #stl #словарь #std

Вопрос:

Итак, я хочу создать простую карту, std::map<T1, std::string> и у меня есть функция, которая возвращает std::string Я хочу каким-то образом связать создание элемента в std::map с моей функцией, чтобы при my_map[some_new_element] вызове вызывалась моя функция, а для ее возврата устанавливалось значение для some_new_element ключа. Возможно ли такое и как это сделать?

Комментарии:

1. Конечно, возможно с помощью какой-то оболочки, но вопрос в том, почему ? В чем смысл карты? Если вам нужно только фиксированное значение, почему бы не вызвать функцию напрямую?

2. Принимает ли ваша функция параметры?

Ответ №1:

Вы можете обернуть саму карту или тип значения или operator[].

Последняя оболочка будет самой простой:

 template <typename T>
std::stringamp; get_default(std::map<T, std::string>amp; map, const Tamp; key) {
    auto it = map.find(key);
    if (it == map.end()) {
        return map[key] = create_default_value();
    } else {
        return *it;
    }
}
  

Тип значения также не должен быть слишком сложным:

 struct default_string {
    std::string wrapped_string;
    default_string() : wrapped_string(create_default_value()) {}
    explicit default_string(const std::stringamp; wrapped_string)
        : wrapped_string(wrapped_string) {}
    operator const std::stringamp;() const { return wrapped_string; }
    operator std::stringamp;() { return wrapped_string; }
};
  

Перенос карты потребует немного больше работы, так как вам пришлось бы дублировать весь интерфейс, включая typedefs. Примечание: этот код не тестировался, рассматривайте его как подтверждение концепции, чтобы направить вас в правильном направлении.

Комментарии:

1. 1 для get_default функции мне не очень нравится создавать новый тип только для принудительного использования одного конкретного конструктора…

Ответ №2:

Как насчет небольшого класса-оболочки для std::string ?

 class StringWrapper {

    StringWrapper() { //... your code
    }

    operator std::stringamp;() { return m_string; } // or something like that
private:
    std::string m_string;
};
  

Теперь вы используете следующий тип карты:

 std::map<T1, StringWrapper> mymap;
  

В конструкторе StringWrapper вы можете определять пользовательские действия. Он вызывается, когда вы вставляете элемент в свою карту.