I am trying to implement a particular template design in C++, and ran into an issue that I wanted to make is solvable. Here is the setup, with explanation of the issue to follow.
I declare an templated abstract base class as follows:
template <class TModel, class TVertex>
class AttributeEvaluator2f
{
public:
virtual void evaluate( TModel& model, TVertex& v, float x, float y ) = 0;
};
I then want to implement sub classes that specialize one of the template parameters, like so:
template <class TVertex>
class SurfacePositionFromSphere : public AttributeEvaluator2f<Sphere3f,TVertex>
{
public:
virtual void evaluate( Sphere3f& sphere, TVertex& v, float theta, float phi )
{
sphere.SamplePosition( v.position, theta, phi );
};
};
I would then instantiate an object based on these classes like this:
SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute();
The compilation error indicates that I never implemented the abstract method the original base class. This is probably because in the subclass, I am declaring the method directly with the first parameter as already specialized (Sphere3f
in this case).
So the question is, is it possible to override an abstract base class method argument's type in this way? If not, is there a similar mechanism that could be used to provide similar functionality?
Thanks in advance for your help!
EDIT: The exact error message is gigantic due to the template unwrapping, but here is the major portion of it for your reference: error C2259: 'Glyph3::AttributeEvaluator2f' : cannot instantiate abstract >class 1> with 1> [ 1> TModel=Glyph3::Sphere3f, 1> TVertex=Glyph3::BasicVertexDX11::Vertex 1> ] 1> due to following members: 1> 'void Glyph3::AttributeEvaluator2f::evaluate(TModel &,TVertex &,float,float)' : is abstract 1> with 1> [ 1> TModel=Glyph3::Sphere3f, 1> TVertex=Glyph3::BasicVertexDX11::Vertex 1> ] 1> c:\users\zij1fh\documents\visual studio 2012\projects\hg3\trunk\hieroglyph3\source\rendering\attributeevaluator2f.h(26) : see declaration of 'Glyph3::AttributeEvaluator2f::evaluate' 1> with 1> [ 1> TModel=Glyph3::Sphere3f, 1> TVertex=Glyph3::BasicVertexDX11::Vertex 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_V0_t &&)' being compiled 1> with 1> [ 1> _Ty=Glyph3::AttributeEvaluator2f, 1> _Objty=Glyph3::AttributeEvaluator2f, 1> _V0_t=Glyph3::AttributeEvaluator2f 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_V0_t &&)' being compiled 1> with 1> [ 1> _Ty=Glyph3::AttributeEvaluator2f, 1> _Objty=Glyph3::AttributeEvaluator2f, 1> _V0_t=Glyph3::AttributeEvaluator2f 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(903) : see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' being compiled
EDIT2: The usage indicated above is not correct (as pointed out by Andy). This is the exact usage that I have:
VertexEvaluator2f< Sphere3f, BasicVertexDX11::Vertex > evaluator;
evaluator.Evaluators.push_back( SurfacePositionFromSphere<BasicVertexDX11::Vertex>() );
Within the VertexEvaluator2f class, I iterate over the attributes to produce a vertex. Here is the declaration of that class as well, for completeness:
template <class TModel, class TVertex>
class VertexEvaluator2f
{
public:
void SetModel( TModel& model ) {
m_Model = model;
};
void evaluate( TVertex& v, float x, float y ) {
for ( auto& evaluator : Evaluators ) {
evaluator.evaluate( m_Model, v, x, y );
}
};
std::vector< AttributeEvaluator2f< TModel, TVertex > > Evaluators;
protected:
TModel m_Model;
};
attribute
– Andy Prowl