7

数値型をラップする (および追加機能を提供する) 型を作成したいと思います。
さらに、数値とラッパーの両方を暗黙的に相互に変換できるようにする必要があります。

これまでのところ、私は持っています:

template<class T>
struct Wrapper
{
    T value;
    Wrapper() { }
    Wrapper(T const &value) : value(value) { }
    // ... operators defined here ...
};

ほぼ問題ありませんが、組み込み型とまったく同じようには動作しません。

#include <iostream>

int main()
{
    unsigned int x1, x2 = unsigned int();
    Wrapper<unsigned int> y1, y2 = Wrapper<unsigned int>();

    std::cerr << x1       << std::endl;  // uninitialized, as expected
    std::cerr << y1.value << std::endl;  // uninitialized, as expected

    std::cerr << x2       << std::endl;  // zero-initialized, as expected
    std::cerr << y2.value << std::endl;  // uninitialized!?!
}

Wrapperそのようなステートメントを設計する方法はありますか

Wrapper<unsigned int> y2 = Wrapper<unsigned int>();

value内部を初期化しますが、のようなステートメントを強制することはありません

Wrapper<unsigned int> y1;

また、同じことをしますか?

つまり、初期化に関して組み込み型とまったく同じように動作する型を作成することは可能ですか?

4

4 に答える 4

3

更新された回答

さて、dyp が指摘するように、私と他の全員が間違っていました。= defaultデフォルトのコンストラクターを使用して、やりたいことを実現できます。

 Wrapper() = default ;
           ^^^^^^^^^

これが機能するのは、初期化子がなくても、前に概説したのと同じ動作が得られるためですが、値の初期化を使用すると、段落8で概説したように動作が変化します。

— T が (おそらく cv 修飾された) 非共用体クラス型であり、ユーザー提供または削除された既定のコンストラクターがない場合、オブジェクトはゼロで初期化され、T に自明でない既定のコンストラクターがある場合は、既定で初期化されます。

元の回答

これをあなたが望むように機能させる方法はないと思います。クラス型は、組み込み型とは異なる動作をします。これは、標準草案セクションの 8.5 初期化子の段落12からわかります (強調して進む):

オブジェクトに初期化子が指定されていない場合、オブジェクトは default-initializedです。初期化が実行されない場合、自動または動的ストレージ期間を持つオブジェクトの値は不確定です。[ 注: 静的またはスレッド ストレージ期間を持つオブジェクトはゼロで初期化されます。3.6.2 を参照してください。—終わりのメモ]

これは、パラグラフ7の組み込み型とはクラスの結果が異なることがわかります。

タイプ T のオブジェクトをデフォルトで初期化するとは、次のことを意味します。

次の箇条書きが含まれます。

— T が (おそらく cv 修飾された)クラス型 (第 9 節) である場合、T のデフォルト コンストラクターが呼び出されます(T にアクセス可能なデフォルト コンストラクターがない場合、初期化の形式は正しくありません)。

— T が配列型の場合、各要素はデフォルトで初期化されます。

それ以外の場合、初期化は実行されません。

そして、2 番目のケースの段落11Wrapper<unsigned int>()を見ると、次のように書かれています。

初期化子が括弧の空のセット、つまり () であるオブジェクトは、値で初期化されます。

そしてパラグラフ8に戻ります:

タイプ T のオブジェクトを値で初期化するとは、次のことを意味します。

— T が (おそらく cv 修飾された)クラス型(第 9 節) であり、デフォルト コンストラクターがない (12.1) か、ユーザー提供または削除されたデフォルト コンストラクターのいずれかである場合、オブジェクトはデフォルトで初期化されます。[...]

したがって、同じ動作になります。

Praetorianascheplerの両方が、わずかに異なる動作をするオプションを提供しましたが、同じ構文ではなく、希望する動作を実現しているように見えます。

于 2014-03-08T05:28:05.210 に答える
0

残念ながら、私が考えることができるわけではありません。C++class_type nameは、既定のコンストラクターを呼び出すように暗黙的に変換します。デフォルトのコンストラクターに、初期化されていないプリミティブ型に期待されることを行わせる必要があります。

于 2014-03-08T05:24:37.527 に答える
0

ユーザー提供のコンストラクターを削除すると、デフォルトの構築時にメンバーを初期化しないままにするか、ラッパーを値で初期化してそのストレージ (したがってそのメンバー) をゼロで初期化することができます。

unsigned int x1, x2 {}; // One uninitialized, one value-initialized
Wrapper<unsigned int> y1, y2 {}; // Ditto

集約初期化を使用して、構築中に値を設定することもできます。

Wrapper<int> z {42};

とにかく、これはほとんど不要です。初期化されていない値は、微妙で再現が難しいバグを導入する場合を除いて、ほとんど役に立ちません。デフォルトのコンストラクターまたはメンバー宣言のいずれかで、メンバーの値を初期化することをお勧めします。

于 2014-03-08T08:40:51.110 に答える