17

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

auto_ptr で op->*() がサポートされていないのはなぜですか、またどのように実装するのでしょうか (私はしばらく実験しましたが、最終的にはあきらめました)。

4

3 に答える 3

8

ルターが指摘しているように、実装するのは自明ではありませんが、可能です。

必ず

  1. テンプレートを使用して、引数の型をoperator->*推測できるようにします
  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)

...必要な作業とこの機能から生じる利益の比率が悪いため、通常は実装されていません。

于 2010-07-17T19:08:18.027 に答える
4

->* を実装するには、完全な転送の問題を解決する必要があります。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm

operator->* は、const、volatile、および参照型を正しく処理して、メンバー オブジェクトへのポインターと同じパラメーター リストを持つ呼び出し可能なオブジェクトを返す必要があります。そして、デフォルトのパラメーターを処理するために特別な魔法の力を使用する必要があります。これは難しく、エラーが発生しやすく、解決できず、コンパイル時間がかかりすぎます。また、メンバーへのポインターは C++ の比較的人気の低い機能であるため、通常、スマート ポインターの実装から除外されます。

于 2010-07-17T18:32:17.327 に答える
0

operator->*私は間違っているかもしれませんが、メンバー関数へのポインターをオーバーロードする方法はないと思います。これはp->*memfun、 が呼び出し可能なオブジェクトとして扱う式の一部として有効である一方で、それ自体では有効な式ではなく、型がないためです。したがって、演算子が返す有効な型はありません。

以下はメンバーへのポインターには機能しますが、メンバーへのポインター関数に使用しようとすると、GCC では「非静的メンバー関数の無効な使用」というエラーが発生し、GCC では内部コンパイラ エラーが発生します。 MSVC。

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

編集:Georgの回答が指摘しているように、boost::bindまたは同様に使用して、固定された最大数の引数までメンバー関数のオーバーロードのセットを作成できますが、可能なすべてのメンバー関数の演算子をオーバーロードする方法はまだありません.

于 2010-07-17T18:32:27.457 に答える