次のコードは、https ://github.com/facebook/folly/blob/master/folly/Synchronized.h から抽出されたものです。
最近、Folly ライブラリを調べたところ、興味深いものが見つかりました。次の例を検討してください。
#include <iostream>
struct Lock {
void lock() {
std::cout << "Locking" << std::endl;
}
void unlock() {
std::cout << "Unlocking" << std::endl;
}
};
template <class T, class Mutex = Lock >
struct Synchronized {
struct LockedPtr {
explicit LockedPtr(Synchronized* parent) : p(parent) {
p->m.lock();
}
~LockedPtr() {
p->m.unlock();
}
T* operator->() {
std::cout << "second" << std::endl;
return &p->t;
}
private:
Synchronized* p;
};
LockedPtr operator->() {
std::cout << "first" << std::endl;
return LockedPtr(this);
}
private:
T t;
mutable Mutex m;
};
struct Foo {
void a() {
std::cout << "a" << std::endl;
}
};
int main(int argc, const char *argv[])
{
Synchronized<Foo> foo;
foo->a();
return 0;
}
出力は次のとおりです。
first
Locking
second
a
Unlocking
私の質問は: なぜこのコードは有効なのですか? このパターンに名前はありますか?
-> 演算子は 2 回呼び出されますが、1 回しか書かれていません。