1

以下のコードの汎用バージョンを実装しようとしています。

#include <iostream>

class ContainerA
{
    public:
        ContainerA( int newData )
            : mData_(newData)
        {}
        int mData_;
};

class ContainerB
{
    public:
        ContainerB( int newData )
            : mData_(newData)
        {}
        int mData_;
};

ContainerA staticInstanceA( 3 );
ContainerB staticInstanceB( 11 );

template< ContainerA* ptrToContainer >
class WorkerOnA
{
    public:
        WorkerOnA( )
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
        }

    private:
        ContainerA* mPtrToContainer_;
};

template< ContainerB* ptrToContainer >
class WorkerOnB
{
    public:
        WorkerOnB( )
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
        }

    private:
        ContainerB* mPtrToContainer_;
};

int main( )
{
    WorkerOnA<&staticInstanceA> workerOnAInstance;
    WorkerOnB<&staticInstanceB> workerOnBInstance;

    workerOnAInstance();
    workerOnBInstance();

    return 0;
}

私が欲しいのは(これが可能であれば)単一のWorkerテンプレートクラスであり、次のように、どちらのコンテナーでも機能するようにインスタンス化できます。

template< ?? ptrToContainer >
class WorkerOnAnyContainer
{
    public:
        WorkerOnA( )
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
        }

    private:
        ?? mPtrToContainer_;
};

しかし、数時間経っても、「??」がどうあるべきかまだわかりません。たぶんテンプレートウィザードはアイデアを持っていますか?

更新1:ワーカーの「operator()」の誤りを修正しました(ptrToContainer-> mPtrToContainer_)。そのために残念。

更新2:何かが機能するようになりましたが、誰かがより良いアイデアを持っているかどうかはまだ興味があります。たとえば、単一のテンプレートパラメータがあると便利です。「テンプレートテンプレートパラメータ」がこの状況で役立つかどうか誰かが知っていますか?

template< class TContainer, TContainer* ptrToContainer >
class Worker
{
    public:
        Worker( )
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
        }

    private:
        TContainer* mPtrToContainer_;
};

ありがとう

4

1 に答える 1

3

試してみます。テンプレートを変更して、ポインター自体ではなく、パラメーターとしてタイプが指定されるようにするのはどうでしょうか。コンストラクターへのポインターを渡すことはできます。

template< typename TContainer >
class WorkerOnAnyContainer
{
    public:
        WorkerOnA( TContainer* ptrToContainer )
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
        }

    private:
        TContainer* mPtrToContainer_;
};

次に、次のように使用できます。

WorkerOnAnyContainer<ContainerA> workerOnAInstance(&staticInstanceA);

テンプレートパラメータとしてのポインタの設計を維持したいので、次のようなものを使用できます。

template< typename TContainer, TContainer* ptrToContainer >
class WorkerOnAnyContainer
{
    public:
        WorkerOnA()
            : mPtrToContainer_(ptrToContainer)
        {}

        void operator()()
        {
            std::cout << "Data = " << ptrToContainer->mData_ << '\n';
        }

    private:
        TContainer* mPtrToContainer_;
};

そしてそれを次のように使用します:

WorkerOnAnyContainer<ContainerA, &staticInstanceA> workerOnAInstance;

ただし、2つのテンプレート引数が必要であり、最初の引数は冗長であると感じるため、これはやや面倒です。これをC++03で解決できるかどうかはわかりませんが、C++11で型の推定を実行できるヘルパーメソッドを作成できると思いました。

template<typename T>
auto CreateWorker(T* container) -> WorkerOnAnyContainer<T, container>
{
    return WorkerOnAnyContainer<T, container>();
}

ただし、コンパイラーは関数が非コンパイル時定数パラメーターに対して機能することを期待しているため、これはコンパイルされません(GCC 4.6.3):

use of parameter 'container' outside function body

これを行おうとしているのはあなただけではないことがわかりました。どうやら、C ++ 11を使用しても、この方法でヘルパーメソッドを作成することはできません。

私が実際に機能すると考えることができるのは、マクロを使用することだけです(私は知っています、私は知っています):

#define CreateWorker(container) WorkerOnAnyContainer<decltype(container), &container>()

次に、それを使用するのは次のように簡単です。

auto worker = CreateWorker(staticInstanceA);    // Note no `&'

これは、IntelC++コンパイラがv12の時点でサポートしている両方のC++11機能を利用してautoおり、単純decltypeです(ただし、このコードはGCC以外ではテストしていません)。もちろん、マクロなので少し壊れやすいです。

実際に見てください!

于 2012-04-15T16:09:28.573 に答える