3

私はヘッダーのみのライブラリを構築しており、コードが示すものと同様のことを行うことで、いくつかの循環依存の問題を解決しました。

基本的に、前方宣言された型が含まれていて前方宣言されていないかのように使用できるようにするプライベート テンプレート実装を作成します。

私のアプローチに危険なことはありますか?

パフォーマンスの低下はありますか? (ライブラリの主な焦点はパフォーマンスです - 実際のコードには明示的なinline提案があります)

おまけの質問:コンパイル時間に (正または負の) 影響はありますか?


// Entity.h
#include "Component.h"
struct Entity { void a() { ... } } 

// Component.h
struct Entity; // forward-declaration
class Component 
{        
    Entity& entity;
    template<class T = Entity> void doAImpl() { static_cast<T&>(entity).a(); } 

    public:
        // void notWorking() { entity.a(); } <- this does not compile
        void doA() { doAImpl(); }
}
4

4 に答える 4

3

私のアプローチに危険なことはありますか?

テンプレートのインスタンス化が実際に延期されている限り、うまくいかないことはほとんどありません。間違ったインスタンス化を禁止すれば、意図をもう少しうまく宣言できるかもしれません。

typename std::enable_if< std::is_same< T, Entity >::value
    && sizeof ( T ) /* Ensure that Entity is not incomplete. */ >::type

コードを 2 回目に読み取ると、非テンプレートdoA関数がすぐに時期尚早にインスタンス化されdoAImpl、テンプレート化が無効になるように見えます。Implパブリック インターフェイスは、関数が実際に使用される場合にのみ、最終的に機能するもののインスタンス化を引き起こす必要があるため、非テンプレートにすることはできないと思います。privateユーザーを保護する別のテンプレート レイヤーがない限り、この部分を削除してすべてを .NET で行う方がよいでしょうdoA

パフォーマンスの低下はありますか?

いいえ。関数は必ずインライン化されます。

コンパイル時間に (正または負の) 影響はありますか?

わずかな複雑さの追加は、確かに違いはありません。


これを行わない唯一の理由は明らかです。それは醜いからです。そして、懸念の分離に違反している可能性が非常に高いです。

1 つの回避策は、代わりに非メンバーのフリー関数を使用することです。

struct Entity;
void a( Entity & );

    void doA() { a( entity ); }

もう 1 つは、単にEntity.hor を依存関係として扱い、それを含めることです。これが最も一般的なソリューションになると思います。

Componentが実際に に依存していない場合は、既存の両方を含む独自の新しいヘッダーを持つ必要がある派生クラスに属している可能性がありますEntitydoA

于 2013-08-19T02:24:22.757 に答える
0

「*.inl」に実装することをお勧めします

// Entity.h

#ifndef ENTITY_H
#define ENTITY_H

class Component; // forward-declaration
struct Entity { void a(); };

#include "Entity.inl" 

#endif

//エンティティ.inl

#ifndef ENTITY_INL
#define ENTITY_INL

#include "Component.h";
inline void Entity::a() { /* implementation using Component and Entity */}

#endif

// Component.h

#ifndef COMPONENT_H
#define COMPONENT_H

struct Entity; // forward-declaration
class Component 
{        
    Entity& entity;
    public:
        void doA();
};

#include "Component.inl"

#endif

// Component.inl

#ifndef COMPONENT_INL
#define COMPONENT_INL

#include "Entity.h";
inline void Component::doA() { entity.a(); }

#endif
于 2013-08-18T12:45:09.257 に答える