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:修复了 Workers (ptrToContainer -> mPtrToContainer_) 的 'operator()' 中的错误。对此感到抱歉。

更新 2:我得到了一些工作,但如果有人有更好的主意,我仍然会很好奇。例如,有一个模板参数会很好。有谁知道“模板模板参数”在这种情况下是否有帮助?

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

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

    private:
        TContainer* mPtrToContainer_;
};

感谢:D

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;

但是,这有点混乱,因为您需要两个模板参数,而第一个参数感觉是多余的。我不确定是否可以使用 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 `&'

这利用了英特尔 C++ 编译器从 v12 开始支持auto的简单decltype的 C++11 特性(尽管我没有用除 GCC 之外的任何东西测试过这段代码)。作为一个宏,它当然有点脆弱。

在行动中看到它!

于 2012-04-15T16:09:28.573 回答