1

最近、C++テンプレートのタイプミスを探すのに時間を費やしました。g ++はタイプミスについて文句を言わなかったので、将来この種の問題をチェックできるツールがあるかどうか疑問に思いました。

これは、正しいコンパイルを示す簡単な例です。構造体ダミーが定義されていないという苦情が予想されますが、テンプレート化されたクラスgooがそれを隠しているようです。

foo.h:

struct smart {
    int x, y, z;
};

template<typename T> class goo
{
    void barf(T* ptr){}
};

template<typename T> class foo 
{
public:
    foo(){};
private:
    goo<T> x;
};

class bar: public foo<struct dummy>
{
public:
    void do_something(struct smart& thing){}
};

foo.cpp:

#include "foo.h"

int main()
{
    bar a;
    struct smart b;
    a.do_something(b);
    return b.x+b.y+b.z;
}

g++foo.cppで正常にコンパイルされます

4

4 に答える 4

3

最高の警告レベルに設定されたコンパイラは、C++ の問題を検出するための最適なツール です

あなたへの私のアドバイスは2つあります:

1) コンパイラの警告レベルを最高レベルに設定します。これにより、下位レベルが沈黙している可能性のある多くの間違いが検出されます。

2) 何か間違ったことをしたときにコンパイラ エラーを生成しやすいコーディング スタイルを使用します。例えば:

class bar: public foo<struct dummy>
{
public:
    void do_something(struct smart& thing){}
};

正直なところ、このコードが合法かどうかはわかりません。そうではないと強く思いますが、新しい type を宣言しているようですstruct dummy。コンパイラはそれを受け入れるので、合法かどうかはわかりません。

代わりにこれを行うことで、あなたは十分に役立ったでしょう:

class bar: public foo<dummy>
{
public:
    void do_something(struct smart& thing){}
};

これを新しい型宣言として解析することはできず、コンパイラはそれを拒否します。これはあなたの問題を早期に発見したでしょう。

于 2012-05-15T18:06:17.303 に答える
2

テンプレート型パラメーターを使用していない場合 (例の場合)、型が存在しない場合や、呼び出されていないメンバー関数の型で関数を呼び出している場合でも、コードは問題ありません。これは、C++ の名前であり、使用しない場合は料金を支払う必要はありません (たとえば、新しい関数は作成されません)。

于 2012-05-15T18:02:55.197 に答える
2

これstruct dummyは、そのような構造体が存在しない場合、前方宣言構造体を自動生成するようにコンパイラに指示されているためです。dummyせずにそのまま使用するstructと、そうはならず、文句を言うでしょう。

于 2012-05-15T18:12:14.430 に答える
0

Attillaはこれを成功させました。の定義dummyは必要ないため、不完全な型のままにすることができます。これは、情報の隠蔽とコンパイル時間の短縮に役立つため、C/C++ の非常に便利な機能です。

例えば:

// Afwd.h
class A;
A * getA ();
void processA(A *);
void printA (A *);


// t.cc
#include "Afwd.h"
void bar ()
{
  A * a = getA ();
  processA (a);
  printA (a);
}

ここでは、クライアントがAその実装の詳細を確認する必要はありません。これには、クライアントがヘッダーの定義に必要なヘッダーを含める必要がないという利点もあります。A

元の例でエラーを生成するにはdummy、この翻訳単位で定義を使用する必要があります。

まず、ptr逆参照など、完全な型を必要とする方法で使用する必要があります。

template<typename T> class goo
{
public:
    void barf(T* ptr){
      *ptr;           
    }
};

barf関数が呼び出されないため、インスタンス化されないため、これはまだ問題ではありません。

template<typename T> class foo 
{
public:
    foo(){
      x.barf (0);
    };
private:
    goo<T> x;
};

このコードでエラーが生成されるようになりました。のコンストラクターは、 をbarインスタンス化し、 の定義をfoo呼び出しますbarf

于 2012-08-02T19:21:00.100 に答える