1

これに関するGoogleの情報は見つかりませんでした。次の例では、次のようになります。

    #include <iostream>

    class Default
    {
    public:
      void Print()
      {
        std::cout << "This is a message\n";
      }
    };

    template <class C = Default>
    class Template
    {
    public:
      static void Test()
      {
        Default oDefault();
      }
    };

    int main()
    {
      return 0;
    }

コードは次のエラーでコンパイルに失敗します:

静的メンバー関数'staticvoid Template :: Test()':19:22:エラー:デフォルトのテンプレート引数は、-std = c++0xまたは-std=gnu++0xがないと関数テンプレートで使用できません。

問題は、その行に角かっこが表示されるのが気に入らないことです。その理由がわかりません。角かっこを削除すると、コードは正常にコンパイルされます。また、テンプレート宣言(13行目)を削除すると、正常にコンパイルされます。これはバグですか、それともまさにこの状況についてどこかにルールがありますか?

私はg++4.6.1(gccバージョン4.6.1(Ubuntu / Linaro 4.6.1-9ubuntu3))を使用しています

4

2 に答える 2

2

次のように変更します。

 Default oDefault = Default();  // Version 1

使用できますが:

 Default oDefault;              // Version 2

これは少し異なる意味を持っています。

  • バージョン1:PODメンバーをゼロで初期化させます(状況によっては)。
  • バージョン2:PODメンバーを初期化しないようにします(状況によっては)。

バージョン1では、追加のコピー構造を呼び出すように見えますが、これは(ほとんどのコンパイラでは)当てはまりません。余分なコピーはコンパイラによって削除され、単純な通常の(ゼロで初期化された)構造が発生するためです。

クラス(または任意のメンバータイプ)にユーザー定義のコンストラクターがない場合(デフォルトのように)のように、デフォルトよりもゼロ初期化を優先する必要があります(デフォルトのように)。違いは、デフォルト初期化ではPODメンバーが未定義のままになり、ゼロ初期化ではPODメンバーはゼロに初期化されました。今、私のクラスにはメンバーがいないと思うかもしれませんので、それは問題ではありません。しかし、クラスを変更すると、すべてのインスタンスを見つけて更新するとどうなりますか。バージョン1を使用して、コンパイラーに正しいことをさせるのが最善です。

すべての心を吹き飛ばす詳細については、以下を参照してください。

最初のバージョンが機能しなかった理由は、それが実際には関数の前方宣言であるためです。これは、C ++の複雑な構文と、覚えておく必要のあるルールの1つが原因です。これは「最も厄介な解析」として検索できます。

于 2012-03-19T04:57:52.450 に答える
1
Default oDefault();

コンパイラーは、これをオブジェクトの作成ではなく、関数宣言と見なします。パラメータを受け取らず、オブジェクトを返す
関数を宣言します。 oDefault()Default

次のように変更します。

Default oDefault;
于 2012-03-19T04:07:24.243 に答える