1

ここのMSDNライブラリで説明されているように、私はpimplイディオムを少し実験したいと思いました。今私Foo.hpp

template<typename T>
class Foo {
public:
    typedef std::shared_ptr<Foo<T>> Ptr;

    Foo();
private:
    class Impl;
    std::unique_ptr<Impl> pImpl;
};

Tパラメータがまだ使用されてない場合。実装はに保存されますFoo.cpp

template<typename T>
class Foo<T>::Impl {
public:
    int m_TestVar;
};

template<typename T>
Foo<T>::Foo() : pImpl(new Impl) {
    this->pImpl->m_TestVar = 0x3713;
}

現在、コンパイラには2つのエラーと1つの警告があります。

  • use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
  • can't delete an incomplete type; ... vc\include\memory in line 1151
  • deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152

ここでの競合とは何ですか?どうすれば解決できますか?

編集。std::make_shared1つの古いバージョンに基づいて、-copy&pastefailの呼び出しを削除しました。

4

2 に答える 2

2

同様の問題が発生しました。システムにという基本クラスNamedComponentがあり、既存の名前付きコンポーネントを取得して、それを単純なファサードに変換するテンプレートを作成したいと思いました。

テンプレートをヘッダーとインラインファイルに分け、テンプレートをインスタンス化する関数を作成しました。これにより、実装がライブラリ内にあり、その実装でファサードのテンプレートがインスタンス化され、クライアントがテンプレートと実装の前方宣言に基づいてファサードを使用できるようになります。

ヘッダー'Foo.h':

template<class T> class Foo
{
public:
    Foo ();
    virtual ~Foo();

private:
    T *impl_;

public:
    // forwarding functions
    void DoIt();
};

インライン関数'Foo.inl':

#include "Foo.h"

template<class T> Foo<T>::Foo() :
    impl_ ( new T )
{
}

template<class T> Foo<T>::~Foo()
{
    delete impl_;
}

// forwarding functions
template<class T> void Foo<T>::DoIt()
{
    impl_ -> DoIt();
}    

// force instantiation
template<typename T>
void InstantiateFoo()
{
    Foo<T> foo;
    foo.DoIt();
}

実装cppファイル-テンプレートインライン関数を含め、実装を定義し、インスタンス化関数を参照します。

#include "Foo.inl"

class ParticularImpl {
public:
    void DoIt() {
        std::cout << __FUNCTION__ << std::endl;
    }
};

void InstantiateParticularFoo() {
    InstantiateFoo<ParticularImpl>();
}

client cpp file-テンプレートヘッダーをインクルードし、実装を前方宣言し、pimplファサードを使用します。

#include "Foo.h"
class ParticularImpl;

int main () {
    Foo<ParticularImpl> bar;

    bar.DoIt();
}

InstantiateFoo関数の内容をいじって、コンパイラにすべての関数をインスタンス化させる必要がある場合があります。私の場合、ベースはテンプレートメソッドですべてのpimplの関数を呼び出したため、1つが参照されると、すべてが参照されました。Instantiate関数を呼び出す必要はなく、それらにリンクするだけです。

于 2013-03-20T14:06:30.073 に答える
1

IMHO PIMPLは、考えられるすべてのテンプレートパラメータを知っていて、そのセットがかなり小さい場合を除いて、テンプレートではあまり意味がありません。問題は、Implコメントに記載されているように、それ以外の場合はヘッダーファイルに実装があることです。可能なTパラメーターの数が少ない場合でも、分離を使用できますが、ヘッダーで特殊化を宣言してから、ソースファイルでそれらを明示的にインスタンス化する必要があります。

ここでコンパイラエラーが発生します。unique_ptr<Impl>の定義が使用可能である必要Implがあります。代わりに、ctorとdtorをそれぞれ直接使用newdelete、スマートポインターの利便性/安全性を落とす必要があります。Foo::FooFoo::~Foo

于 2013-03-20T12:58:15.937 に答える