7

Boost実装によって作成された素晴らしいトリックを見てきました。彼らはどういうわけか、()演算子のオーバーロードを使用して、クラスboost :: system::error_codeのインスタンスをbool値に評価します。

class error_code
{
...
typedef void (*unspecified_bool_type)();
static void unspecified_bool_true() {}

operator unspecified_bool_type() const  // true if error
{ 
  return m_val == 0 ? 0 : unspecified_bool_true;
}
...
}

これにより、次のようなエラーをチェックできるようになります。

...
boost::system::error_code err

some_boost_func(err);
if(err)
{
    //handle error
}
....

だから私は自分自身に尋ね続けます..そこで何が起こったのですか?これはどういうわけか関数ポインタの使用に関連しているようです...これを呼び出すとerr、関数自体または関数ポインタが評価されますか?しかし、関数はどのようvoid (*unspecified_bool_type)();にして値を返すことができますか

return m_val == 0 ? 0 : unspecified_bool_true;
4

1 に答える 1

15

特に関数ポインターのコア機能とはほとんど (またはまったく) 関係がありません。これは、クラスに対して「安全な」ブール型の変換を記述できるようにするトリックです。

ifあるクラスを(そして通常は論理コンテキストで)使用できるようにしたい場合、通常、クラスをに変換可能にしboolます。のように

class Error {
public:
  operator bool() const { /* whatever */ }
};

そして今、あなたはできる

Error err;
...
if (err) // automatically intepreted as `if (err.operator bool())`
  ...

ただし、bool型は C++ の整数型であるため、誰かが誤って次のようなものを書いた場合、これは望ましくない結果につながる可能性があります。

int i = err;

またはerr算術式で使用すると、静かにコンパイルされます。

このため、多くの場合、人々は への変換ではなく、ポインタ型への変換を導入することを好みますbool

class Error {
public:
  operator void *() const { 
    // Return null pointer for `false` and any non-null pointer for `true`
  }
};

これは の下ifで使用できるので優れていますが、 では以前の間違いを犯すことはできませんint。いえ

 if (err) // automatically interpreted as `if (err.operator void *() != 0)`
   ...

errコンパイラはオブジェクトをポインタ型に自動的に変換するため、コンパイルして意図したとおりに動作します。

ただし、そのような変換は (ブール値のコンテキストに加えて) ポインターのコンテキストにも自動的に適用されます。つまり、誤って行うことができます。

void *p = err;

また

free(err);

静かにコンパイルされます。これも望ましくない。

このようなエラー クラスを誤って誤用することをより困難にするために、関数へのポインターなど、より「エキゾチックな」ポインター型を使用することをお勧めします。これはまさに、引用したコードに表示されるものです。はunspecified_bool_typeポインタベースの疑似ブール型として使用されます。に対してはヌル値が返され、 に対してはダミー関数falseへのポインタが返されます。関数が呼び出されることはなく、呼び出されることも意図されていません。戻り値として使用される一意のポインター値を予約するためだけに存在します。unspecified_bool_truetrueunspecified_bool_truetrue

場合によっては、さらに一歩進んで、さらに「エキゾチックな」ポインター型、つまりクラス メンバーへのポインター型を使用する人もいます。しかし、ほとんどのアプリケーションでは、関数へのポインターは十分に「エキゾチック」です。

于 2012-07-11T06:40:17.847 に答える