I want to do something like this:
template <typename T:public Vertex> addTri( T v1, T v2, T v3 )
{
// Take v1.pos, v2.pos, v3.pos and create a geometric repn..
Triangle tri( v1.pos, v2.pos, v3.pos ) ; // all vertices will
// have to have a .pos member.
// Create the vertex buffer..
VertexBuffer<T> vb ...
}
Since that doesn't work, this is my workaround..
template <typename T> addTri( T v1, T v2, T v3 )
{
Vertex* p1 = (Vertex*)&v1 ;
// This is a very "shut up C++, I know what I'm doing" type cast.
// I'd like for C++ to know that all vertex types (T in this case)
// __will__ have a Vector member .pos.
Triangle tri( p1->pos, p2->pos, p3->pos ) ;
// Create the vertex buffer..
VertexBuffer<T> vb ...
}
In case you're interested, I'm trying to write a general bit of code to handle triangle creation.
Each vertex has to have a .pos
member, because each vertex has to have a position in space.
However not every vertex type will have a texture coordinate. Not every vertex will have a color. Hence the parameterized types.
A similar approach is used in XNA VertexBuffer.SetData<T>
.
You cannot specify a type restriction in the template type argument. However, generally, you don't have to.
If you simply do:
template <typename T> addTri( T v1, T v2, T v3 )
{
Vertex &v1r = v1;
// ....
}
This will work if the function is instantiated with a derivative of Vertex. It will create an (obscure) error if T &
is not convertible to Vertex &
.
If you don't even care if the types are convertible to Vertex
as long as they have the same members, you can even skip the assignment - C++ template arguments essentially work using duck typing; if you do v1.x
, and T
contains a member named x
, then it will work, whatever type T
might actually be.
You can be a bit more sophisticated using boost's type-traits library and a static assertion; with this, you can start defining an assertion to make the error a bit easier to understand:
template <typename T> addTri( T v1, T v2, T v3 )
{
BOOST_STATIC_ASSERT_MSG(boost::is_convertible<T&, Vertex&>::value,
"Template argument must be a subclass of Vertex");
Vertex &v1r = v1;
// ....
}
A combination of enable_if
, is_base_of
and is_convertible
typetraits should do the job:
template <typename T>
struct Foo : public std::enable_if<std::is_base_of<YourBase, T>::value &&
std::is_convertible<T&, A&>::value,
T>::type
{
// consider "using YourBase::foo;" directives here
};
The type traits are available from <type_traits>
in modern compilers, or <tr1/type_traits>
or Boost otherwise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With