回答:
typedefを転送できます。しかしすること
typedef A B;
最初に転送宣言する必要がありますA
:
class A;
typedef A B;
typedef
、前方宣言を使用して複雑なマルチレベルテンプレートタイプに名前を付ける場合、この方法はかなり複雑で困難です。言うまでもなく、デフォルトのテンプレート引数に隠された実装の詳細に飛び込む必要があるかもしれません。そして、最終的な解決策は、元の型が非常に変更されやすい、長くて読めないコード(特に、型がさまざまな名前空間に由来する場合)です。
typedefを使用して定義されたCスタイルの構造体を前方宣言しようとしている私のようなあなたのために、いくつかのc ++コードで、次のような解決策を見つけました...
// a.h
typedef struct _bah {
int a;
int b;
} bah;
// b.h
struct _bah;
typedef _bah bah;
class foo {
foo(bah * b);
foo(bah b);
bah * mBah;
};
// b.cpp
#include "b.h"
#include "a.h"
foo::foo(bah * b) {
mBah = b;
}
foo::foo(bah b) {
mBah = &b;
}
「fwdがtypedefを宣言する」には、クラスまたは構造体をfwd宣言する必要があり、次にtypedef宣言された型を使用できます。複数の同一のtypedefがコンパイラーによって受け入れられます。
長い形式:
class MyClass;
typedef MyClass myclass_t;
ショートフォーム:
typedef class MyClass myclass_t;
C ++(プレーンCではない)では、両方の定義が完全に同一である限り、型を2回typedefすることは完全に合法です。
// foo.h
struct A{};
typedef A *PA;
// bar.h
struct A; // forward declare A
typedef A *PA;
void func(PA x);
// baz.cc
#include "bar.h"
#include "foo.h"
// We've now included the definition for PA twice, but it's ok since they're the same
...
A x;
func(&x);
A
、A
は定義により空なので、このようにフィールドをどのように定義しますか?
型を宣言するには、そのサイズがわかっている必要があります。型へのポインタを転送宣言するか、型へのポインタをtypedefできます。
本当に必要な場合は、pimplイディオムを使用してインクルードを低く抑えることができます。しかし、ポインタではなく型を使用したい場合、コンパイラはそのサイズを知っている必要があります。
編集:j_random_hackerは重要な資格をこの回答に追加します。基本的に、型を使用するにはサイズを知っておく必要がありますが、型へのポインタまたは参照を作成するために型が存在することだけを知る必要がある場合は、前方宣言を行うことができます。タイプ。OPはコードを表示しませんでしたが、コンパイルできないと不平を言ったので、OPは単に参照するだけでなく、型を使用しようとしていると(おそらく正しく)想定しました。
前方宣言を使用する代わりにフルの#include
Sは、あなたがしている場合のみ可能ですません(このファイルの範囲内)型自体が、それへのポインタまたは参照を使用して意図します。
タイプ自体を使用するには、コンパイラーがそのサイズを知っている必要があります-したがって、その完全な宣言を確認する必要があります-したがって、完全なもの#include
が必要です。
ただし、ポインターまたは参照のサイズは、指示先のサイズに関係なくコンパイラーに認識されているため、前方宣言で十分です。型識別子の名前を宣言します。
興味深いことに、ポインター、参照、class
またはstruct
型を使用する場合、コンパイラーは不完全な型を処理できるため、先の型も転送宣言する必要がなくなります。
// header.h
// Look Ma! No forward declarations!
typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere
typedef class A& ARef;
typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere
typedef struct B& BRef;
// Using the name without the class/struct specifier requires fwd. decl. the type itself.
class C; // fwd. decl. type
typedef C* CPtr; // no class/struct specifier
typedef C& CRef; // no class/struct specifier
struct D; // fwd. decl. type
typedef D* DPtr; // no class/struct specifier
typedef D& DRef; // no class/struct specifier
同じ問題があり、異なるファイルに複数のtypedefをいじりたくなかったので、継承で解決しました。
だった:
class BurstBoss {
public:
typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with...
した:
class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool>
{
public:
ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) {
};
};
魅力のように働いた。もちろん、参照を変更する必要がありました
BurstBoss::ParticleSystem
単に
ParticleSystem
typedef
(using
具体的に)を継承とコンストラクター継承(?)に置き換えました。
元の
using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;
交換済み
struct CallStack // Not a typedef to allow forward declaration.
: public std::array<StackFrame, MAX_CALLSTACK_DEPTH>
{
typedef std::array<StackFrame, MAX_CALLSTACK_DEPTH> Base;
using Base::Base;
};
このようにして、私は前方宣言CallStack
をすることができました:
class CallStack;
Bill Kotsiasが述べたように、ポイントのtypedefの詳細を非公開にし、それらを前方宣言する唯一の合理的な方法は、継承を使用することです。ただし、C ++ 11を使用すれば、これを少しうまく行うことができます。このことを考慮:
// LibraryPublicHeader.h
class Implementation;
class Library
{
...
private:
Implementation* impl;
};
// LibraryPrivateImplementation.cpp
// This annoyingly does not work:
//
// typedef std::shared_ptr<Foo> Implementation;
// However this does, and is almost as good.
class Implementation : public std::shared_ptr<Foo>
{
public:
// C++11 allows us to easily copy all the constructors.
using shared_ptr::shared_ptr;
};
@BillKotsiasのように、私は継承を使用し、それは私のために働いた。
私はこの混乱を変更しました(私の宣言* .hにすべてのboostヘッダーが必要でした)
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>
typedef boost::accumulators::accumulator_set<float,
boost::accumulators::features<
boost::accumulators::tag::median,
boost::accumulators::tag::mean,
boost::accumulators::tag::min,
boost::accumulators::tag::max
>> VanillaAccumulator_t ;
std::unique_ptr<VanillaAccumulator_t> acc;
この宣言に(* .h)
class VanillaAccumulator;
std::unique_ptr<VanillaAccumulator> acc;
実装(* .cpp)は
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>
class VanillaAccumulator : public
boost::accumulators::accumulator_set<float,
boost::accumulators::features<
boost::accumulators::tag::median,
boost::accumulators::tag::mean,
boost::accumulators::tag::min,
boost::accumulators::tag::max
>>
{
};