У меня вопрос об изменении элементов в контейнере boost::multi_index. У меня есть структура, содержащая некоторые предопределенные параметры и ряд параметров, которые определяются во время выполнения и хранятся в карте. Вот упрощенная версия структуры:
class Sdata{
QMap<ParamName, Param> params; // parameters defined at run-time
public:
int num;
QString key;
// more pre-defined parameters
// methods to modify the map
// as an example - mock version of a function to add the parameter
// there are more functions operating on the QMAP<...>, which follow the same
// rule - return true if they operated successfully, false otherwise.
bool add_param(ParamName name, Param value){
if (params.contains(name)) return false;
params.insert(name, value);
return true;
}
};
Теперь я хочу перебрать различные комбинации предопределенных параметров Sdata. Для этого я пошел на boost::multi_index:
typedef multi_index_container<Sdata,
indexed_by <
// by insertion order
random_access<>,
//by key
hashed_unique<
tag<sdata_tags::byKey>,
const_mem_fun<Sdata, SdataKey, &Sdata::get_key>
>,
//by TS
ordered_non_unique<
tag<sdata_tags::byTS>,
const_mem_fun<Sdata, TS, &Sdata::get_ts>
>,
/// more keys and composite-keys
>//end indexed by
> SdataDB;
И теперь я хочу получить доступ и изменить параметры внутри файла QMap<...>
.
Q1 Правильно ли я понимаю, что для изменения любого поля (даже не связанного с индексом) нужно использовать функторы и делать что-то, как показано ниже?
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, Functor(...))
Q2 Как получить результат метода с помощью функтора? То есть у меня есть функтор:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
sdata.remove_param (name); // this returns false if there is no param
}
};
Как узнать, вернул ли remove_param true
или false
в этом примере:
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
l.modify(it, SdataRemoveParam("myname"));
До сих пор я пришел к тому, чтобы генерировать исключение, чтобы метод modify
boost::multi_index при использовании с функтором Rollback
возвращал false
:
struct SdataRemoveParam : public std::unary_function<Sdata, void>{
ParamName name;
SdataRemoveParam(ParamName h): name(h){}
void operator ()(Sdata &sdata){
if (!sdata.remove_param (name)) throw std::exception("Remove failed");
}
};
// in some other place
Sdatas_byKey const &l = sdatas.get<sdata_tags::byKey>();
auto it = l.find(key);
bool res = l.modify(it, SdataRemoveParam("myname"), Rollback);
Однако мне это решение не нравится, потому что оно увеличивает риск удаления записи из контейнера.
Q3 есть ли решения получше?