auto_ptr (shared_ptr также) пытаются сделать свое использование максимально прозрачным; то есть, идеально, Вы не должны мочь сказать различие, используете ли Вы auto_ptr или реальный указатель на объект. Рассмотрите:
class MyClass
{
public:
void foo() { }
};
MyClass* p = new MyClass;
auto_ptr<MyClass> ap(new MyClassp);
p->foo(); // No notational difference in using real
ap->foo(); // pointers and auto_ptrs
Когда Вы пытаетесь вызвать функцию членства через указатель на участника, существует различие, поскольку auto_ptr, очевидно, не реализует op-> * ():
void (MyClass::*memfun)() = &MyClass::foo;
(p->*memfun)(); // OK
(ap->*memfun)(); // Error op->*() missing
(ap.get()->*memfun)(); // OK
Почему не там никакая поддержка op-> * () в auto_ptr и как можно было бы реализовать его (я экспериментировал в течение некоторого времени, но в конечном счете сдался).
реализация -> * потребует решения идеальной проблемы пересылки:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/ Оператор n1385.htm
-> * должен возвращать вызываемый объект с тем же списком параметров, что и объект указателя на член, правильно обрабатывая константные, изменчивые и ссылочные типы. И тогда ему пришлось бы использовать особые магические способности для обработки параметров по умолчанию. Это сложно, подвержено ошибкам, неразрешимо и отнимает слишком много времени на компиляцию, а поскольку указатели на члены являются сравнительно незначительно популярной функцией C ++, они обычно не используются в реализациях интеллектуальных указателей.
Я могу ошибаться, но думаю, что нет способа перегрузить оператор -> *
для функции-указателя на член. Это потому, что p -> * memfun
, хотя и действителен как часть выражения, которое рассматривает его как вызываемый объект, не является правильным выражением само по себе и не имеет типа. Следовательно, нет допустимого типа для возврата оператором.
Следующее будет работать для указателя на член, но попытка использовать его для функции указателя на член приводит к ошибке «недопустимое использование нестатической функции-члена» с GCC и внутренним ошибка компилятора с MSVC.
template <class CLASS, typename MEMBER>
MEMBER& operator->*(std::auto_ptr<CLASS>& p, MEMBER CLASS::*m)
{
return (*p).*m;
}
РЕДАКТИРОВАТЬ: как указывает ответ Георга, вы можете использовать boost :: bind
или аналогичный для создания набора перегрузок для функций-членов до фиксированного максимального количества аргументов, но по-прежнему нет возможности перегрузить оператор для всех возможных функций-членов.
Как указывает Лютер, его нетривиально реализовать, но это возможно.
Вы должны
-> *
operator ()
с подписью, эквивалентной функции-члену Игнорирование квалификаторов для момента, вот как это может в основном выглядеть (используя C ++ 0x, чтобы избежать повторения вручную):
// pointer to data member:
template<class T, class D>
D& operator->*(std::auto_ptr<T>& p, D T::*mp) {
return (*p).*mp;
}
// pointer to member function:
template<class T, class R, class... Args> struct Callable {
typedef R (T::*MFP)(Args...);
MFP mfp;
T& instance;
Callable(T t, MFP mfp) : instance(t), mfp(mfp) {}
R operator()(Args... a) {
return (instance.*mfp)(a...);
}
};
template<class T, class R, class... Args>
Callable<T, R, Args...>
operator->*(std::auto_ptr<T>& p, R (T::*mfp)(Args...)) {
return Callable<T, R, Args...>(*p, mfp);
}
Но, в конце концов, зачем беспокоиться, когда мы можем просто использовать функторы, которые в первую очередь связывают указатели на элементы.
Хотя я не могу быть в этом уверен, но если вы объедините знание того, что
(* p). * m
) ... это, вероятно, обычно не реализуется из-за плохого соотношения требуемой работы и выигрыша в результате этой функции.