Это возможно без изменения текущего синтаксиса.
Вам придется заставить inst << a
(то есть текущий operator<<
) возвращать временный экземпляр "специального" класса, содержащего ссылку на inst
, реализуя operator<<
, вызывая inst.operator<<
, возвращая ссылку на *this
, а затем выполняя дополнительную работу в своем деструкторе, который будет вызываться в конце оператора.
И да,Вы можете отслеживать количество вызовов с ним.
Я предлагаю следующие не члены operator<<
перегрузки (vw_chain
- новый прокси-класс):
// Left-most operator<< call matches this
vw_chain operator<<(vw &inst, const int &a) {
return vw_chain(inst, a);
}
// All subsequent calls within the << chain match this
vw_chain &&operator<<(vw_chain &&chain, const int &a) {
chain.insert(a);
return std::move(chain);
}
Сам класс:
struct vw_chain
{
explicit vw_chain(vw &inst, const int &a) :
inst(inst)
{
insert(a);
}
~vw_chain() {
// do something
}
void insert(const int &a) {
// This, the original operator<<, should be made accessible only to this
// function (private, friend class declaration?), not to cause ambiguity.
// Or, perhaps, put the implementation of the original operator<< here
// and remove it altogether.
inst << a;
++insertion_count;
}
vw &inst;
size_t insertion_count = 0;
};
Мы должны передать экземпляр по ссылке rvalue.Мы делаем первую вставку внутри конструктора vw_chain
, чтобы получить обязательную копию elision (C ++ 17), которая работает только с prvalues.Будет ли копия сделана в операторе return
, не определено в NRVO и более старых стандартах.Мы не должны полагаться на это.
Решение до C ++ 17:
struct vw_chain
{
// We keep the constructor simpler
vw_chain(vw &inst) : inst(inst) {}
// Moved-from chains are disabled
vw_chain(vw_chain &&other) :
inst(other.inst),
insertion_count(other.insertion_count) {
other.is_enabled = false;
}
// And will not call the termination logic
~vw_chain() {
if(is_enabled) {
// do something
}
}
void insert(const int &a) {
inst << a;
++insertion_count;
}
vw &inst;
size_t insertion_count = 0;
bool is_enabled = true;
};
// The first overload changes to this
vw_chain operator<<(vw &inst, const int &a) {
vw_chain chain(inst);
chain.insert(a);
return chain;
}