2010-12-30 19 views
1

C++の呼び出し元のために翻訳する必要があるDSLに由来するコードがいくつかあります。 #include依存関係をC++でどのようにソートするかを理解する必要があります。幸いにも、私は自分の仕事をより簡単にできるいくつかの制限があります。C++の#include依存関係を自動的にソート

  1. 結果にテンプレートやマクロが含まれていません。私は人生を楽にするためにテンプレートやマクロを使うことができますが、DSLはそれらを必要とするものを明示的に生成しません。すべての前処理、コード生成はそのために行われます。
  2. 結果のコードは、読み込み可能または保守可能である必要はありません。プログラムによって生成され、消費されることになります。好ましくは、パフォーマンス上の罰則を伴わないか、オプティマイザを混乱させることはありませんが、それが必要ならば私は生きることができます。

しかし、私は法的C++なプログラムを記述するいくつかのコードを変換する必要がありますが、そのようなこれまでのところ、私は私が作るでしょうアイデアを思い付いた

struct X { 
    Y y; 
    Y func(); 
}; 
struct Y { 
    X func(); 
}; 
// or 
struct Y { 
    void func(X x); 
}; 
struct X { 
    void func(Y y); 
}; 

として、定義されることはありません各タイプは独立したヘッダを持ちますが、実装ファイルでは実装が依存するすべての型を#includeできますが、これはあまり難しくありません。問題は、これが可能になるようにXとYのコードをどのように変更できるかです。

今、私はRVOとNRVOを適用し、議論のために幾分似通ったことをすることを考えました。しかし、実際には最適化ではなく、実際には可能でないケースはありませんか?これはMSVC10で書かれているので、C++ 0xが提供する追加機能に対処できます。

編集:自分のニーズを少し控えめにしているので、自分のコードを編集しました。 RVOとNRVOもこれをカットすることはできません。

編集編集:関数の戻り値と引数で前方宣言で十分であれば、データメンバーのインクルード注文をトポロジカルに並べ替えることができます。結局のところ、何かをすることはまだ合法ではない

struct X { 
    Y y; 
}; 
struct Y { 
    X x; 
}; 

答えて

1

トポロジカルな並べ替えを行う方法です。

これでうまくいかない場合は、shared_ptrなどを使用してコードを変換する必要があります。

1

なぜ前方宣言を使用しないのですか?宣言で、その後、使用するすべてのタイプの前方宣言によってそれを

struct Y; 
struct X { 
    Y func(); 
}; 
struct Y { 
    X func(); 
}; 

あなたは、その独自のヘッダに、すべての型宣言を置くことができ、先頭に追加:あなたはXとYをこのように宣言した場合

あなたの例では、完全に大丈夫です実装ファイルには、使用された型のすべてのヘッダが含まれています。型宣言で使用されるすべての型を前方宣言する場合、最初に含めるファイルを心配する必要はありません。それは問題ではありません。

それを合計するには、次の

headerA.h

#pragma once 
class B; 

class A { 
    B b; 
public: 
    void myfunc(); 
}; 

headerB.h

#pragma once 
class A; 

class B { 
    A a; 
}; 

implA.cpp

#include "headerA.h" 
#include "headerB.h" 

void A::myfunc() { 
    // ... 
} 

T無関係なコードでタイプAを使用するときは、headerA.hheaderB.hの両方を含める必要があります。あなただけのheaderA.hを含めたい場合は、タイプAを使用する場合、ヘッダをこのように調整します

headerA.h

#pragma once 
class B; 
#include "headerB.h" 

class A { 
    B b; 
public: 
    void myfunc(); 
}; 

headerB.h

#pragma once 
class A; 
#include "headerA.h" 

class B { 
    A a; 
}; 

を包含警備員は残りの世話をします。

+1

エラーC2079: 'X :: y'は未定義の構造体 'Y'を使用します。不完全な型は完全に定義された型のように使用することはできません。両方の提案されたヘッダーがエラーになります。 – Puppy

+0

@DeadMG [OK]を、私はそれらの型を使用してインラインコードは、コンパイラが言うもののために動作しないことを述べている必要があります。ヘッダファイルに実際に関数本体がある場合は、使用する型の完全宣言を含めるか、それらの本体をcppファイルに移動する必要があります。 – Fiktik

+0

@DeadMGまた、いくつかのコードでタイプAを使用する場合は、headerA.hとheadedB.hの両方を明示的にインクルードする必要があります。 – Fiktik

0

引数を引数で渡すか、XまたはYに依存しない中間データ型を作成して渡します。サイズ/インタフェースが利用できないため、実際には値の問題によるリターン/パスの回避は不可能です。そのままでは、それらは共依存している。

別のオプションは、両方を同じクラスインターフェイスで宣言することです。

テンプレートと特殊化を使用することはできますが、定義を書く意思がない限り、維持するのは面倒です。ジェネレータはこのオプションを提供します。

+0

実際には、名前で知られているクラスを値渡しで渡すコードは問題ありません。これは、呼び出し元と呼び出し先が定義を必要とするため、呼び出しは明確に定義されていますが、「外部者」はこれを必要とせず、そのような関数を安全に無視することができます。 – Macke

関連する問題