2016-07-19 7 views
6

C++クラスライブラリでエラー処理の概念を移行する作業を進めています。以前は単純にbool(成功/失敗)を返したメソッドは、機械可読のエラーコードと人間が解読可能な説明(ここでは関係ありません)を伝えるResultオブジェクトを返すように変更されます。C++:代入演算子を「明示的」にすることはできますか

何千行ものコード行を処理するのはエラーが起こりやすいため、私はこの作業のためにコンパイラから最適なサポートを得ようとします。

マイ結果クラスが持っている - 他のメンバメソッドのうち - コードのコードと代入演算子の結果を構築:

class Result 
{ 
    public: 
     typedef unsigned long ResultCode; 
     explicit Result(ResultCode code); // (1) 
     Result& operator=(ResultCode code); // (2) 
}; 

備考:私は通常ResultCodeため列挙クラスを使用するに私の問題を解決するだろうが、これは選択肢ではない。これは、主な設計目的が異なるライブラリでResultを使用することでした。各ライブラリは、すべてのライブラリの可能なすべての結果コードを定義する1つの大きなヘッダーファイルを必要とせずに独自の結果コードセットを定義するためです。実際には、各クラスは局所的な結果コードを定義して、可能な結果コードのリストをクラスのヘッダーから取得できるようにしなければならない。したがって、コードはResultで列挙できません。クラスはResultクラスを使用して定義する必要があります。クライアントコードで

return true; 

書類に暗黙の型変換を避けるために

、コンストラクタは明示的に宣言されています。しかし、ネストメソッド呼び出しでは、別の問題が発生します。私はResultオブジェクトを返す関数で使用しています方法

bool doSomething() 
{ 
    return true; 
} 

を持っている、と言います。暗黙的に変換される)のdoSomethingのブール戻り値( - 私は、これは私のコンパイラエラーを与えるつもりはない、ネストされた呼び出しResultの代入演算子の現在の実装では

Result doSomethingElse 
{ 
    Result result = doSomething(); 
    return result; 
} 

の結果コードを転送したいです符号なしlong。

私はC++のドキュメントを読んでいるので、コンストラクタと変換演算子だけを明示的に宣言することができます。

私の質問

  1. 明示的な代入演算子または他の方法のために許可されていないのはなぜ? IMOでは、どのメソッドも明示的にすることができるようにするのは非常に意味があります。
  2. 代入演算子の暗黙的な型変換を防ぐ他の解決策がありますか?あなたが投稿したコードに関して
+1

私はそれはあなたが望む答えではないと知っているが、なぜC++の例外メカニズムを使用しないように「キャッチ」何unsigned intをされていないのテンプレートoverloadngを使用して、それを強制することができますか?言語と戦わないでください。それを使って作業してください。 (プラス、うまくポーズされた質問のためにプラス)。 – Bathsheba

+2

'template void operator =(T)= delete;'を宣言できませんでした。それは通常の場合にそれを使用し、他のすべてのタイプに対して削除されたメソッドを使用しようとします。 – doug65536

+0

私はそれが可能であるかどうかは分かりませんが、あなた自身がそれを作るのではなく、[システムエラークラス](http://en.cppreference.com/w/cpp/error#System_error)を拡張する可能性があります? –

答えて

1

With the current implementation of Result's assignment operator, this is not going to give me a compiler error - the boolean return value of doSomething() is implicitly converted to unsigned long.

。エラーerror: no viable conversion from 'bool' to 'Result'see hereが発生します。

コードに表示される動作を示す最小限の例が必要です。コードに重大な影響を及ぼす実際のコードには、他のコンストラクタや型変換がある可能性があります。明示的に尋ねた質問で


...

Why is explicit not allowed for assignment operators or other methods?

explicit

が唯一の暗黙の型変換が行われることができる場所を許可されている、つまり、コンパイラは特別な存在である(あなたのための変換を生成しようとする場所 boolの場合)。そのような変換は、コンストラクタと変換(またはキャスト演算子)です。

コンストラクタまたは変換演算子をexplicitと指定すると、コンパイラは変換を行わないため、変換が必要な場合は明示する必要があります。これがなぜ行われるのかの一般的な動機として、それが何をしているかをより明確に示します。トレードオフがあるので、どちらの場合でも慎重な使用を適用する必要があります。一般的なアドバイスは疑問があるときにexplicitを好むことです。

たとえば、

struct Result { 
    Result(long src); // can be marked explicit 
    operator long() const; // can be marked explicit 
}; 

Are there other solutions to prevent implicit type conversion for the assignment operator?

代入演算子はResult& operator=(Result&);ための特定を有しています。割り当て自体には変換はありません。代入に対してResultを暗黙的に作成しないようにするには、コンストラクタにexplicitというマークを付ける必要があります。

からResultが作成されないようにするには、メソッドを宣言するか、削除済みとしてマークすることができます。

Result& operator=(ResultCode code) = delete; 
+0

変換されていない場合、結果result = trueの舞台裏で何が起こっているのですか。それは私に1の結果コードを残します –

+0

どのコンパイラを使用していますか?それはgcc、clang、msvcのエラーです。 – Niall

+0

@kritzel_sw。コンパイルを示す最小限の例がありますか(期待どおりではありません)? – Niall

2

あなたの問題は、クラスResultではありません:あなたは明示結局、それの新しいインスタンスを作成しています。 はそれを禁止できません。

暗黙のプロモーションbool -> longを禁止することはできません。

あなたはそれを回避することができます。 1つの方法は、ResultCodeではなく、を整数型にすることです。 は明示的なコンストラクタを持つことができます。

class ResultCode 
{ 
unsigned long m_code; 
public: 
explicit ResultCode(unsigned long code) : m_code(code) {} 
operator unsigned long() { return m_code; } 
}; 

のようなものは、あなたがResultCodeどこでもunsigned intを使用してResultCode res = 5またはreturn ResultCode(5)としてそれを作成するが、ResultCode期待して関数を呼び出すことはできません使用することができるようになる(例えばResultコンストラクタなどを!)ではないものとResultCodeが既にあります。関数がReturnCodeを返さなければならない場合は、return 5のように何もしないでください。

そうしないと、エラー

typedef unsigned long ResultCode; 

class Result 
{ 
    ResultCode m_par; 

public: 
    template<typename T> 
    Result(T param) { static_assert(false); } 

    template<> 
    Result(ResultCode par): m_par(par) {} 
}; 

int main() 
{ 
    ResultCode a = 5;  //ok 
    //unsigned long a = 6; //also ok 
    //bool a = true;  //error! 
    //int a = 7;   //also error!! 
    Result b(a); 
} 
関連する問題