Почему не делает поддержки auto_ptr op-> * ()

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 и как можно было бы реализовать его (я экспериментировал в течение некоторого времени, но в конечном счете сдался).

17
задан PiotrNycz 22 June 2015 в 13:06
поделиться

3 ответа

реализация -> * потребует решения идеальной проблемы пересылки:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/ Оператор n1385.htm

-> * должен возвращать вызываемый объект с тем же списком параметров, что и объект указателя на член, правильно обрабатывая константные, изменчивые и ссылочные типы. И тогда ему пришлось бы использовать особые магические способности для обработки параметров по умолчанию. Это сложно, подвержено ошибкам, неразрешимо и отнимает слишком много времени на компиляцию, а поскольку указатели на члены являются сравнительно незначительно популярной функцией C ++, они обычно не используются в реализациях интеллектуальных указателей.

4
ответ дан 30 November 2019 в 14:28
поделиться

Я могу ошибаться, но думаю, что нет способа перегрузить оператор -> * для функции-указателя на член. Это потому, что p -> * memfun , хотя и действителен как часть выражения, которое рассматривает его как вызываемый объект, не является правильным выражением само по себе и не имеет типа. Следовательно, нет допустимого типа для возврата оператором.

Следующее будет работать для указателя на член, но попытка использовать его для функции указателя на член приводит к ошибке «недопустимое использование нестатической функции-члена» с GCC и внутренним ошибка компилятора с MSVC.

template <class CLASS, typename MEMBER>
MEMBER& operator->*(std::auto_ptr<CLASS>& p, MEMBER CLASS::*m)
{
    return (*p).*m;
}

РЕДАКТИРОВАТЬ: как указывает ответ Георга, вы можете использовать boost :: bind или аналогичный для создания набора перегрузок для функций-членов до фиксированного максимального количества аргументов, но по-прежнему нет возможности перегрузить оператор для всех возможных функций-членов.

0
ответ дан 30 November 2019 в 14:28
поделиться

Как указывает Лютер, его нетривиально реализовать, но это возможно.

Вы должны

  1. использовать шаблоны, чтобы можно было вывести тип аргументов для оператора -> *
  2. позаботьтесь о возможных квалификаторах и множественных функциональных объектах, используя перегрузки
  3. для члена указатели на функции возвращают объект callabe, который:
    • , привязанный к экземпляру, на который интеллектуальный указатель указывает на
    • , реализует 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 )

... это, вероятно, обычно не реализуется из-за плохого соотношения требуемой работы и выигрыша в результате этой функции.

8
ответ дан 30 November 2019 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: