指向模板类的全局实例模板作为模板参数?

时间:2012-04-15 16:04:12

标签: c++ templates global-variables non-type

我正在尝试实现以下代码的通用版本:

#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的'operator()'中的错误(ptrToContainer - &gt; mPtrToContainer_)。对不起。

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

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

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

    private:
        TContainer* mPtrToContainer_;
};

谢谢, d

1 个答案:

答案 0 :(得分: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>();
}

但是,由于编译器希望该函数适用于非编译时const参数,因此不能编译(GCC 4.6.3):

use of parameter 'container' outside function body

结果是you're not the only one trying to do this。显然,即使使用C ++ 11,也无法以这种方式创建辅助方法。

我能想到的唯一可行的方法就是使用宏(我知道,我知道):

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

然后使用它就像:

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

这使用了auto和一个简单的decltype,这两个C ++ 11的功能都是英特尔C ++编译器从v12开始支持的(虽然我没有用GCC以外的任何东西测试过这个代码) 。作为一个宏观,它当然有点脆弱。

See it in action!