2012-11-16 18 views
8

私がC++でプログラミングしているときに、JavaScriptのようなすべての変数にundefinedという値があることを望みます。 は、私は、配列の範囲外の要素の値を返すよ例えば、例外をundefinedを返す代わりに投げるために有用であった、または:(私の意見では)無効な参照を返す

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
    static T badref; 
public: 
    T &operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else 
     throw std::string("OUT-OF-BOUNDS"); // or: return badref; !! 
    } 
}; 

別汚いですオプションは、事前定義変数の参照を不正な参照変数として戻しています。 nullなどを参照変数に割り当てることはできません。

呼び出し元が返された値が正しくないことを知ることができる参照を返すためのパターンが整っていますか?

EDIT:私はあなたが彼のコメントで述べたよう@クリスブースト::オプションを使用することができますpointer

+5

はい、ポインタと呼ばれます。代わりに、 'boost :: optional'があります。 – chris

+2

少なくとも、あなたのbadrefオブジェクトを静的にしておけば、あなたが作成したすべてのMyArrayでスペースを取ることはありません。しかし、私は同意する、それは醜いです。そのようなジェネリックコードでは、むしろ例外をスローします。 – john

+0

@john:はい、私はそれを編集しました。 – deepmax

答えて

5

を意味していませんよ。 Boost libaryの一部として提供されています。詳細は、this pageを参照してください。

修正クラス:

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
public: 
    optional<T&> operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return optional<T&>(arr[i]); 
    else 
     return optional<T&>(); 
    } 
}; 

使用法:あなたは、あなたのソリューションは、型システムに適合するために必要と思うものは何でも

MyArray<int>() array; 
// fill array with data 

optional<int&> result = array[0]; 
if (result) { 
    // item was found 
} else { 
    // index out of bounds 
} 
+0

badrefは何ですか? –

+0

@DenisErmolin私は個人的には、operator ::の戻り値が定義されていない可能性があることを明示しているので、boost :: optionalを好むので、この条件をチェックする必要があります。 @MasoudM。 –

+0

私は私の答えを編集し、ドキュメントのためのリンクを追加しました。 Boostについての詳細は、http://www.boost.org/doc/libs/1_52_0/index.html –

2

。したがって、関数のシグネチャは、結果がTである可能性があると明示的に言わなければなりませんが、それは別のものかもしれません。

  • 代わりの値を返し、ステータスコードと出力が「アウト」パラメータ(ポインタまたは参照)を介して値を返す:であることのために

    一般的な方法

    bool tryGet(int i, T& result); 
    
  • 戻りタプル(ステータス値)等:

    std::tuple<bool, T> get(int i) 
    

    (Cの場合ouldn't取得するには、二組の要素が無関係考える - デフォルトコンストラクタを持つようにTが必要です)

  • )使用boost::variant(フレキシブルますが、ブーストを必要と

  • 使用boost::optional(上記の簡単なバージョン、ときに唯一の私はJavascriptのようなすべての変数に何かのために未定義の値があったことを望む
3

)「T・オア・ナッシングのいずれかを」必要があります!

は、あなただけのポインタ(nullptr)のための "未定義" の値を持っています。参照は、(定義によって)有効なインスタンスを指すものです。

はあなたのオペレータののconstと非constの値の間で区切る必要があり、静的オブジェクトへの参照を返すには:

template <typename T, int SIZE> 
class MyArray 
{ 
    T arr[SIZE]; 
    static T badref; 
public: 
    T &operator[](int i) 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else 
     // returning ref here would allow clients to write: 
     // MyArray<int> a; 
     // a[-1] = 5; // valid if you return a non-const reference 
     throw std::string("OUT-OF-BOUNDS"); 
    } 
    const T &operator[](int i) const 
    { 
    if (i >=0 && i < SIZE) 
     return arr[i]; 
    else { 
     // MyArray<int> a; 
     // a[-1] = 5; // will not compile (cannot assign to const) 
     static const T invalid = T(); 
     return invalid; 
    } 
    } 

};

0

参照の主な目的は、無効な(NULL)値を避け、関数が引数を変更してデータをコピーしないようにすることです。 NULL値が必要な場合は、ポインタを使用します。

関連する問題