I am trying to implement a generic version of the code below:
#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;
}
What I would like to have (if this is possible at all) is a single Worker template-class, which can be instantiated to work on either container, something like:
template< ?? ptrToContainer >
class WorkerOnAnyContainer
{
public:
WorkerOnA( )
: mPtrToContainer_(ptrToContainer)
{}
void operator()()
{
std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
}
private:
?? mPtrToContainer_;
};
However, after several hours, I still can’t figure what the ‘??’s should be. Maybe a template-wizard has an idea?
Update 1: Fixed mistake in ‘operator()’ of Workers (ptrToContainer -> mPtrToContainer_). Sorry for that.
Update 2: I got something working, but I would still be curious if anyone has a better idea. For example, having a single template-parameter would be nice. Does anyone know if “template template parameters” can help in this situation?
template< class TContainer, TContainer* ptrToContainer >
class Worker
{
public:
Worker( )
: mPtrToContainer_(ptrToContainer)
{}
void operator()()
{
std::cout << "Data = " << mPtrToContainer_->mData_ << '\n';
}
private:
TContainer* mPtrToContainer_;
};
Thanks,
D
I’ll give it a shot. How about changing your template so that it’s given the type as a parameter, instead of the pointer itself? You can still pass in a pointer to the constructor:
Then you could use it like:
Since you want to keep the pointer-as-template-parameter design, you could go with something like this:
And use it like:
But, this is kinda messy since you need two template arguments, and the first one feels redundant. I’m not sure it’s possible to solve this with C++03, but I figured it would be possible to build a helper method that can do the type deduction for us in C++11:
But, since the compiler expects the function to work for non-compile-time-const parameters, this doesn’t compile (GCC 4.6.3):
It turns out you’re not the only one trying to do this. Apparently, you can’t create a helper method this way, even with C++11.
The only thing I can think of that actually works is to use a macro (I know, I know):
Then using it is as simple as:
This makes use of
autoand a simpledecltype, both C++11 features that the Intel C++ compiler supports as of v12 (though I haven’t tested this code with anything except GCC). Being a macro, it is, of course, a bit fragile though.See it in action!