インターフェイスに関しては、次のように単純なクラスがあります。
struct Foo
{
inline Foo & operator << (int i)
{
return *this;
}
};
次に、次の方法で使用できます。
Foo foo;
foo << 1 << 2 << 3 << 4;
ここで、この演算子の使用を制限したいと思います。たとえば、シーケンス ポイント間で偶数回呼び出されるようにします。
私は現在、内部プロキシ クラスを使用してこの問題に対処しています。制御シーケンスの最後に破棄され、オペレーターが呼び出された回数をチェックするテンポラリが作成されます。
struct Foo
{
inline Foo() : m_count(0) {}
private:
struct FooProxy
{
friend struct Foo;
inline ~FooProxy();
inline struct Foo & operator << (int i);
private:
inline FooProxy(struct Foo &foo) : m_foo(foo) {}
struct Foo &m_foo;
};
public:
inline FooProxy operator << (int i);
private:
int m_count;
};
inline Foo::FooProxy Foo::operator << (int i)
{
++m_count;
return FooProxy(*this);
}
inline Foo & Foo::FooProxy::operator << (int i)
{
++m_foo.m_count;
return m_foo;
}
inline Foo::FooProxy::~FooProxy()
{
assert(m_foo.m_count % 2 == 0);
}
いくつかの注意点がありますが、ほとんどの場合、次のように機能します。
Foo foo;
foo << 1 << 2 << 3 << 4; /* is OK */
foo << 1 << 2 << 3; /* triggers an assert */
同じプロキシ手法を使用するか、別の戦略を使用して、コンパイル時にこれを強制する方法があるかどうか疑問に思っています。
私が達成したいことの別の例:int
任意の数がfloat
オペレーターに渡された後、少なくとも 1 つを強制的にプッシュします。
foo << 1 << 2 << 3.f << 4.f << 5; /* is OK */
foo << 1 << 2 << 3.f << 4.f; /* illegal because one `int` is needed */