Re: extending interfaces with variadic templates...
Luca Risolia wrote:
On 12/10/2012 20:03, Werner wrote:
Hi All,
I want to try the following:
typedef CurveMetaDataIF<QPen,QBrush> BrushPenIF;
where the amount of elements in CurveMetaDataIF can be arbitrary.
BrushPenIF would be used as follows:
brushPenIF_->getData<QBrush>();
brushPenIF_->getData<QPen>();
Is this what you want?
template<class... T>
struct CurveMetaDataIF : public T... {
template <class DataT>
DataT getData()
{
return static_cast<DataT*>(this)->getDataImpl();
}
};
struct QPen {
QPen getDataImpl() const { /* do something; */ return *this; }
};
struct QBrush {
QBrush getDataImpl() const { /* do something; */ return *this; }
};
typedef CurveMetaDataIF<QPen, QBrush> BrushPenIF;
int main() {
BrushPenIF brushPenIF_;
brushPenIF_.getData<QBrush>();
brushPenIF_.getData<QPen>();
return 0;
}
Thank you for your response. I've replied via
googlegroups yesterday but it seems it's discarded
my message - grrr. No, your solution is not what I
want, as the interface only provides the data (is
not the data). An implementation needs to exist that
provides the data (See below):
I have a various types of curves that need to be
drawn on a plot. The curve data (series) comes from a
model, but I want meta data relating to the curve
to be provided by an interface. Various types
of meta data might exist (and may depend on state).
The meta data provider, even though the type provided
may be different may have the same implementation
(classically multiple inheriting from more than one
interface, but having one implementation)
Independent curves may exist too, and each curve might
use different meta data I'll use pen and brush as
example:
struct InterfaceToPenData
{
virtual Pen getPen() const = 0;
virtual ~InterfaceToPenData(){}
};
struct InterfaceToBrushData
{
virtual Pen getPen() const = 0;
virtual ~InterfaceToBrushData(){}
};
struct CurveX_MetaData : InterfaceToBrushData, InterfaceToPenData{ ... };
class CurveX
{
public:
explicit Curve( std::shared_ptr<CurveX_MetaData> );
};
CurveY might exist with other combinations of meta data. We
don't want to anticipate the types of meta data that may
be required by the Curves, hence the general solution
(as described in my first post):
Therefore CurveX becomes:
typedef InterfaceToMetaData<QPen,QBrush> CurveX_InterfaceToMetaData;
Curve X
{
explicit (Curve std::shared_ptr<CurveX_InterfaceToMetaData> );
//...
};
Now, how to write InterfaceToMetaData???
My first stab was as described in my first post, but this
has the problem that the typelist needs to be parsed to
call the correct virtual function (on a base higher up
in the hierarchy). The implementation itself would inherit
from the InterfaceToMetaData.
InterfaceToMetaData<QPen> <--
InterfaceToMetaData<QBrush> <--
CurveX_InterfaceToMetaData <--
MetaDataProvider //Provides Meta data based on program state
// Might provide meta data to various curves...
My problem lies over here:
template <class DataT>
DataT getData()
{
return this->getDataImpl( boost::identity<DataT>() );
}
I cannot use the this pointer, as my inheritance
hierarchy is linear (perhaps it should be flat...as yours
are), the latter hiding the function of the
former. My solution was to search for the right base:
template <class DataT>
DataT getData()
{
typedef typename FindBase<DataT>::type BaseT;
return BaseT::getDataImpl( boost::identity<DataT>() );
}
I suppose I could use something like this:
template <class ... MetaDataElements>
class InterfaceToMetaData : SomeDecoration<MetaDataElements>::type ...
{
//and the rest of your solution
};
I've managed to implement FindBase, but I've been wondering
what a good implementation of meta function FindBase would
look like. Also, what would SomeDecoration<MetaDataElements>
look like?
Hope this makes things clearer.
Kind regards,
Werner