Недавно я столкнулся со случаем, когда у меня была константная функция-член, выполняющая операцию и возвращающая результат. Например,
class Foo { ...
Foo add(Foo const & x) const;
}
Но кто-то другой непреднамеренно вызывал его, как будто он обновлял объект this
(игнорируя результат):
Foo a = ...;
Foo b = ...;
a.add(b);
(На самом деле эта ошибка была вызвана несовершенным рефакторингом.)
Есть ли способ заставить последнюю строку выше вызвать ошибку или предупреждение? Следующей лучшей вещью будет перехват во время выполнения, который в основном рассматривается в следующем шаблоне. Однако это убивает оптимизацию возвращаемого значения, как видно из результата счетчика.
template<typename T>
class MustTake {
T & obj;
bool took;
public:
MustTake(T o) : obj(o), took(false) {}
~MustTake() { if (!took) throw "not taken"; }
operator T&() { took = true; return obj;}
};
struct Counter {
int n;
Counter() : n(0) {}
Counter(Counter const & c) : n(c.n+1) {}
~Counter() {}
};
Counter zero1() {
return Counter();
}
MustTake<Counter> zero2() {
return Counter();
}
int main() {
Counter c1 = zero1();
printf("%d\n",c1.n); // prints 0
Counter c2 = zero2();
printf("%d\n",c2.n); // prints 1
zero1(); // result ignored
zero2(); // throws
return 0;
}
Я полагаю, что могу улучшить неэффективность, используя макрос, чтобы MustTake‹> был только отладочным и не выполнялся для выпуска.
Я ищу решение времени компиляции. В противном случае я ищу лучшее решение во время выполнения.
-Wunused-result
, чтобы включить предупреждение об этом. - person Xeo   schedule 22.06.2011a.add(b)
, я бы сразу подумал о мутаторе. Как насчетa.newListWithHead(b)
или чего-то подобного, в зависимости от того, что на самом деле происходит? Не так лаконично, какadd
, но добавление — это не то, чем вы здесь занимаетесь. - person clstrfsck   schedule 22.06.2011a + b
(если это имеет смысл), и тогда все будут знать, что a + b не изменяет a, но они могут легко написать += b, чтобы получить желаемый эффект (я считать). - person David Grayson   schedule 22.06.2011-Wunused-result
существует, работает, задокументировано и по умолчанию включено. - person Dietrich Epp   schedule 22.06.2011warn_unused_result
. Просто слишком много системных функций, наряду с самимnew
, где нет предупреждения о том, чтобы уронить на пол абсолютно необходимый результат. Это хуже, чем рвота. Это половинчатая реализация. - person David Hammen   schedule 22.06.2011warn_unused_result
, msvc++ имеетMustCheck
: из другого поста о переполнении стека - person Tim   schedule 22.06.2011