安全なブールイディオムを適用してブールラッパー構造体を設計しようとしています。
これを解決するための古典的な実装は非常に簡単です。スケルトンは次のようなものです。
struct Bool final
{
Bool() = default;
Bool(bool value)
: _value{value}
{}
explicit operator bool() const {
return _value;
}
private:
bool _value{false};
};
私が改善しようとしている部分は、Bool
の構築方法です。
たとえば、設計による暗黙のナローイングを避けたいです。
Bool b1(45); // yields warnings, but it compiles
Bool b2{3}; // not ok by standard
テンプレートを使用して自分を傷つけようとしましたが、成功しませんでした。
どうすればそれを機能させることができますか?
これは、他のすべてのコンストラクターを明示的に削除することで実現できます。
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
テンプレートコンストラクターを追加し、明示的に削除します。
template <typename T>
Bool(T) = delete;
他のコンストラクタよりも実際のbool
以外のものに一致するため、暗黙的な変換が防止されます。
必要な場合:
「true」または「false」のみであり、暗黙的にint/char/pointerに変換できない変数の場合、列挙型クラスを使用して調べます。
enum class Bool {
False,
True,
};
安全なブールイディオムを適用してブールラッパー構造体を設計しようとしています。
しないでください。
安全なブールイディオムはC++ 03以前にのみ関連します。ここで、タイプが「真実」であることを次のように表現する場合、
struct A {
operator bool() const;
};
あなたは次のようなあらゆる種類の問題に遭遇します:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
したがって、安全なブールイディオムは、関数ポインター(もちろん、関数ポインター!)を使用して、この偶発的な暗黙の変換問題の解決策でした。
C++ 11では、方法が優れていますソリューションがあります。
struct A {
explicit operator bool() const;
};
これは正確に必要なことを行います。実際、この問題を解決するのは 文字通り設計された でした。安全なboolイディオムはかなり複雑な足場ですが、explicit operator bool
は非常に簡単に使用でき、正しいことを行うだけです。そのためのラッパーは必要ありません-実際にexplicit operator bool
を直接記述するよりも、ラッパーを使用する方が難しいです。
さらに、ラッパーは(a)Bool
をfinalにし、(b)同期を維持する必要がある追加のbool
メンバーを作成したため、ユーザーに非課税性を課します。問題を解決するより。実装するのにどれだけ多くの作業が必要かを検討してください。
template <class T>
struct my_unique_ptr : Bool { ... };
対
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};