まず、特定のオブジェクトで機能する一連の論理演算を定義することから始めます。次に例を示します。
// This is just a simple wrapper for the first argument
template <typename T>
struct FirstOp
{
FirstOp(T const& v) : _v(v)
{ }
T const & operator*() const { return _v; }
T const& _v;
};
template <typename T>
struct AndOp
{
AndOp(T const& v) : _v(v)
{ }
T const & operator*() const { return _v; }
// Then hack the stream operator
template <typename O>
O const & operator>>(O const & o) const
{
if (o)
o = o && _v; // assumes T supports safe bool
return o;
}
T const& _v;
};
template <typename T>
struct OrOp
{
OrOp(T const& v) : _v(v)
{ }
T const& operator*() const { return _v; }
// Then hack the stream operator
template <typename O>
O const & operator>>(O const & o) const
{
if (!o)
o = o || _v; // assumes T supports safe bool
return o;
}
T const& _v;
};
template <typename Op1>
struct ResultOf
{
ResultOf(Op1 const& cOp) : _o1(cOp), _r(*_o1)
{ }
ResultOf const & operator=(bool r) const
{ _r = r; return *this; }
operator bool() const { return _r; }
// Then hack the stream operator
template <typename O>
ResultOf& operator>>(O& o)
{
o >> *this;
return *this;
}
Op1 const& _o1;
mutable bool _r;
};
次に、IsGood
パラメータを受け入れるようにを定義し、より多くのパラメータをサポートするためにオーバーロードします。
template <typename T1, typename T2>
bool IsGood(T1 const& t1, T2 const& t2)
{
return ResultOf<T1>(t1) >> t2;
}
その後、次のように呼び出すことができます。
int main(void)
{
std::cout << IsGood(FirstOp<int>(0), OrOp<int>(1)) << std::endl;
}
したがって、このアプローチで可能になったのは、特定の論理演算に使用する値をその演算でラップしてから、それを総称IsGood
関数に渡すことです。ここで、構築される実際の演算子はハードコーディングされていますが、たとえばファイルからこれを読み取り、に渡す適切な演算子を構築することを妨げるものは何もありませんIsGood
。注:上記は短絡であるため、必要に応じて引数を評価するだけです(関数呼び出しが行われます)が、式は評価されません。上記のアプローチを使用して、任意に複雑な論理関係を作成できるはずです。
免責事項:これはあなたの問題についての私の限られた理解です...それがマークから外れている場合は、まあ...