すべて。私はC++にかなり慣れていないので、C ++で小さなライブラリ(主に自分のプロジェクト用)を作成しています。型階層を設計する過程で、代入演算子を定義する問題に遭遇しました。
この記事で最終的に到達した基本的なアプローチを採用しました。つまりMyClass
、クラスから派生した階層内のすべてのクラスに対して、次のBase
ように2つの代入演算子を定義します。
class MyClass: public Base {
public:
MyClass& operator =(MyClass const& rhs);
virtual MyClass& operator =(Base const& rhs);
};
// automatically gets defined, so we make it call the virtual function below
MyClass& MyClass::operator =(MyClass const& rhs);
{
return (*this = static_cast<Base const&>(rhs));
}
MyClass& MyClass::operator =(Base const& rhs);
{
assert(typeid(rhs) == typeid(*this)); // assigning to different types is a logical error
MyClass const& casted_rhs = dynamic_cast<MyClass const&>(rhs);
try {
// allocate new variables
Base::operator =(rhs);
} catch(...) {
// delete the allocated variables
throw;
}
// assign to member variables
}
私が関わっているのは、型の同等性のアサーションです。私はライブラリを書いているので、おそらく最終結果からアサーションがコンパイルされるので、これにより、次のようなスキームを使用するようになりました。
class MyClass: public Base {
public:
operator =(MyClass const& rhs); // etc
virtual inline MyClass& operator =(Base const& rhs)
{
assert(typeid(rhs) == typeid(*this));
return this->set(static_cast<Base const&>(rhs));
}
private:
MyClass& set(Base const& rhs); // same basic thing
};
しかし、コンパイル時に型を確認できるかどうか疑問に思っていました。Boost.TypeTraitsを調べて、やることで近づきましたBOOST_MPL_ASSERT((boost::is_same<BOOST_TYPEOF(*this), BOOST_TYPEOF(rhs)>));
が、rhsは派生クラスではなく親クラスへの参照として宣言されているため、チョークしました。
考えてみると、私の推論はばかげているようです。関数がインラインであるため、実際のパラメーター自体をチェックできることを期待していましたが、もちろん、プリプロセッサーは常にコンパイラーの前に実行されます。しかし、コンパイル時にこの種のチェックを強制できる他の方法を誰かが知っているかどうか疑問に思いました。