web-dev-qa-db-ja.com

C ++セーフboolラッパー

安全なブールイディオムを適用してブールラッパー構造体を設計しようとしています。
これを解決するための古典的な実装は非常に簡単です。スケルトンは次のようなものです。

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

テンプレートを使用して自分を傷つけようとしましたが、成功しませんでした。

どうすればそれを機能させることができますか?

41

これは、他のすべてのコンストラクターを明示的に削除することで実現できます。

struct Bool final
{
    template<class T>
    Bool(T) = delete;

    Bool(bool value);
};
58

テンプレートコンストラクターを追加し、明示的に削除します。

template <typename T>
Bool(T) = delete;

他のコンストラクタよりも実際のbool以外のものに一致するため、暗黙的な変換が防止されます。

24
yuri kilochek

必要な場合:
「true」または「false」のみであり、暗黙的にint/char/pointerに変換できない変数の場合、列挙型クラスを使用して調べます。

enum class Bool {
    False,
    True,
};
18
pilkch

安全なブールイディオムを適用してブールラッパー構造体を設計しようとしています。

しないでください。

安全なブールイディオムは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; }
};
14
Barry