Код:
template <typename T, typename U>
class create_map
{
std::map<T, U> m_map;
public:
create_map(const T& key, const U& val)
{
m_map[key] = val;
}
create_map<T, U>& operator()(const T& key, const U& val)
{
m_map[key] = val;
return *this;
}
operator std::map<T, U>()
{
return m_map;
}
};
Цель этого кода - определить карту с определенными парами ключ / значение путем объединения вызовов в operator()
, например
create_map<int, std::string>( 1, "blah" )( 2, "hah" )( 3, "doh" )
Поскольку класс не имеет конструктора по умолчанию, его нельзя использовать для создания пустой карты.Это может быть по замыслу.Или это может быть ошибка проектирования.
operator std::map<T, U>()
{
return m_map;
}
определяет преобразование в std::map<T, U>
, которое является конечным результатом всего этого.
Это может бытьвызывается неявно везде, где указано create_map
и ожидается std::map
, например, использование выражения create_map
в качестве аргумента в вызове функции.
Однако это может быть довольно неэффективно, поскольку копирует карту,Компилятор вполне может оптимизировать копирование.Но не стоит без надобности полагаться на качество реализации (хотя иногда это лучшее, что можно сделать).
Так что вместо этого должно быть
operator std::map<T, U> const& () const
{
return m_map;
}
const
в концепозволяет create_map
быть объявленным как const
и использоваться.
При таком преобразовании в ссылку возникает та же проблема, что и при использовании аргументов ссылки, а именно теоретическая возможность создания псевдонимов, когда код, который сохраняетссылка на const
не готова к изменениям упомянутого объекта.Но на практике это не проблема.Например, в качестве формального аргумента каждый просто пишет std::string const& s
(вместо просто std::string s
) как само собой разумеющееся, и очень мало, если какие-либо ошибки возникают в результате этого - у меня никогда не возникало никаких проблем.
Приветствия & hth.,