オーバーライドされた等価演算子を使用して同じインタフェースのテンプレート実装を比較する際に問題があります。消去と相互運用性のタイプ:C++での仮想バイナリ演算子の問題
Interface* ptr1 = ...; Interface* ptr2 = ...;
*ptr1 == *ptr2;
私が思いついたてきた唯一の解決策は、同一実装されたオブジェクトを比較するようにしていると、このような比較を実施することを強制することです:
class Interface {
public:
virtual ~Interface() {}
virtual bool operator==(const Interface&) const = 0;
};
template <typename T> class Impl : public Interface {
public:
bool operator==(const Interface& rhs) const {
assert(typeid(rhs) == typeid(const Impl&));
const Impl& rhsRef = static_cast<const Impl&>(rhs);
// ...
}
};
この溶液中の問題は、それがあるということです私の目的にはあまりにも制限されています - 私は、さまざまな実装を比較できるようにしたいと思います。実装数が限られている場合は、ダブルディスパッチパターンを使用することができます。しかし、私の場合のImplはテンプレートなので、それは仮想関数テンプレートが必要になるため、二重派遣は、不可能です。
// This obviously doesn't work.
class Interface {
public:
virtual ~Interface() {}
virtual bool operator==(const Interface&) const = 0;
template <typename T2> virtual bool operator==(const Impl<T2>&) const = 0;
};
template <typename T> class Impl : public Interface {
public:
bool operator==(const Interface& rhs) const {
return rhs == *this;
}
template <typename T2> bool operator==(const Impl<T2>& rhs) const {
// ...
}
};
は、任意の解決策はありますか?私はAnyIteratorクラスを書く必要があります。これはSTLイテレータをラップすることができます。それらは、異なるタイプの周りに巻かれている場合でも、私は例のイテレータとconst_iteratorのために、AnyIteratorsを比較することはできません。
std::list<int>::iterator it1 = ...; std::list<int>::const_iterator it2 = ...;
AnyIterator<const int> myIter1 = it1; AnyIterator<const int> myIter2 = it2;
it1 == it2; // This works perfectly.
myIter1 == myIter2; // This doesn't work!
前のセクションで書いたように、別のSTLイテレータをラップしたAnyIteratorsを比較するには、これが必要です。 AnyIteratorにはイテレータインターフェイスへのポインタが含まれています。イテレータは、保持しているSTLイテレータのタイプによって異なる実装が可能です。だから私はインターフェイスのoperator ==を宣言せずに比較を実装する可能性はないと思う。 – lizarisk
@lizarisk:2つの 'std :: vector :: iterator'を比較することはできません。彼らは同じベクトルを指し示す必要があります。 2つのコンテナのイテレータを比較するのはUBです。このような機能を追加する必要がある場合は、元のコンテナを保存する必要があります。 'void *'として格納すると、両方のイテレータが同じコンテナから来ているかどうかをまず調べることができます。そうであれば、とにかく基本型は1つだけです。そうでなければ、すぐに 'false'を返します。 –
MSalters