4


2

演算子bool()はstd :: stringに変換され、演算子std :: string()と競合します
クラスで演算子std

stringを宣言し、それ自体で文字列への暗黙的な変換としても機能する場合、演算子bool()はどのようにエラーを引き起こすことができますか?

#include
#include
using namespace std;

class Test {
public:
    operator std::string() { cout << "op string" << endl; return "whatever";}
    operator bool() { cout << "op bool" << endl; return true;}
};

int main(int argc, char *argv[]) {
    string s;
    Test t;
    s = t;
}

3 Answer


8


あなたが直面している問題( `operator std

string()`がブール値を返すことを除く)は、暗黙の変換が必要なときとそうでないときにトリガーされることです。

コンパイラが s = t`を検出すると、次の潜在的な std

operator = `の一致を識別します。

// using std::string for compactness instead of the full template
std::string::operator=( std::string const & );
std::string::operator=( char );

現在、 `t`はそれらのどちらでもないので、収まるものに_convert_しようとし、2つのパスを見つけようとします。 コンパイラは実際に決定できず、あきらめます。

これは、多くの異なる変換演算子の提供を避けたい理由の1つです。 コンパイラーによって暗黙的に呼び出される可能性のあるものはすべて、最終的に呼び出されるべきだと思わないときに呼び出されます。

このhttp://www.artima.com/cppsource/safebool.html[article]は、特にこの問題を扱っています。 提案は、「bool」への変換を提供する代わりに、メンバー関数への変換を提供することです

class testable {
   typedef void (testable::*bool_type)();
   void auxiliar_function_for_true_value() {}
public:
   operator bool_type() const {
      return condition() ? &testable::auxiliar_function_for_true_value : 0;
   }
   bool condition() const;
};

このクラスのインスタンスが条件内で使用される場合( if(testable()))、コンパイラは条件で使用できる `bool_type`に変換しようとします。

編集

このソリューションでコードがどのように複雑であるかについてのコメントの後、いつでも汎用の小さなユーティリティとして提供できます。 コードの最初の部分を提供すると、複雑さがヘッダーにカプセル化されます。

// utility header safe_bool.hpp
class safe_bool_t;
typedef void (safe_bool_t::*bool_type)();
inline bool_type safe_bool(bool);

class safe_bool_t {
   void auxiliar_function_for_true_value() {}
   friend bool_type safe_bool(bool);
};
inline bool_type safe_bool(bool)
{
   return condition ? &safe_bool_t::auxiliar_function_for_true_value : 0;
}

これで、クラスははるかに単純になり、それ自体で読みやすくなりました(関数と型に適切な名前を選択することにより)。

// each class with conversion
class testable {
public:
   operator bool_type() {
      return safe_bool(true);
   }
};

読者が「safe_bool」イディオムがどのように実装されているかを知り、彼らが満たすヘッダーを読むことに興味がある場合にのみ、複雑さに直面します(コメントで説明できます)


4


演算子std

string()は、boolではなく文字列を返す必要があります。


1


デビッド・ロドリゲスが正しく指摘しているように、「bool」を「char」に昇格させると、あいまいなオーバーロードが発生します。

stlでは、クラスをテスト可能にすることは通常、「void *」への変換を介して行われます。 あなたがするとき

while (istream.getline()) {
}

istreamはhttp://www.cplusplus.com/reference/iostream/ios/operator_voidpt/[operator void *]でNULLを返すため、ループ条件はfalseに解決されます。

一部の人々は、これは理論的にはできるほど良い解決策ではないと主張している

void* streamptr = istream;
delete streamptr;

しかし、私の意見では、誰かがそのようなポインターを削除し始めたら…​ 彼はstlコード(またはそのことについてはC ++)の近くでは許可されません。