call of overloaded is ambiguous: functions using template classes


M

mast4as

Hi everyone

I have 2 problems related to the same code: one is compile problem
which I am not to sure to solve and the other one is to figure out a
better solution to get cleaner more elegant code. I have 2 classes
normal3 and vector3 which are in essence almost identical. The reason
why I separate them is because in CG they are not transformed the
same. Anyway this is not C++ related... But it's important to separate
them anyway. Now Vector3 and Nomal3 are in essence vector so I shall
be able to do things with them such as dot or cross product or
normalizing them. Because I wasn't able to come up with a better way I
first created 2 classes and then wrote 2 functions for the cross
products which both take 2 vector3 as parameters. But one returns a
vector and the other returns a normal. But when I try to compile ...
the compiler stops on this code (full code at the bottom of the post):

Vector3f edge1 = vert1 - vert0;
Vector3f edge2 = vert2 - vert0;
Vector3f pvec = cross( dir, edge2 );

It doesn't make sense to me because it was quite clear in that case
that cross should return a vector since the object on the left of the
equal sign is a vector ? So why does it say:

xxxx.cppp: In function ‘int xxxxx(const Point3f&, const Vector3f&,
const Point3f&, const Point3f&, const Point3f&, float&, float&,
float&)’:
xxxxx.cpp:277: error: call of overloaded ‘cross(const Vector3<float>&,
Vector3f&)’ is ambiguous

So my first question is how can I remove this error ? (and it would be
great if I could understand what I am doing wrong). Could be that I
use templated classes ?

//////////////

The second question is more a C++ design/architecture one. And it
would be fantastic is anyone could tell me what's the best way of
solving this problem in C++. This seems out of the scope of my
comprehension right now but would really love to progress on this and
come up with a better solution:

As I said in the beginning Vector and Normal share almost all the same
code. The difference is how they are transformed by matrices. So I
don't mind creating two classes for them but what bugs me is that I
have to duplicate all the code... So what I would like to do is to
come with a solution where I can write the code for functions such as
cross, normalize and dot only once and then later do things such as:

Normal3f N = cross( Vector3f( 1, 0 , 0 ), Vector3f( 0, 1, 0 ) );

I don't care if the the result of the cross function which could be a
vector3f is converted to a normal3f type but it doesn't seem to be
able to do this automatically. In other words I guess, I am trying to
find way of making them assignable even though they don't have the
same type. I know it's like going the basic principle of how C++ work
but I am sure there's something clever:

Normal3f n = Vector3f( 10 );
Vector3f vv = Normal( 1.5 );
Normal3d n1 = normalize( vv );
Vector3f vv1 = normalize( n );

It would be great if someone could share his/here experience with me
on this topic as well. Thanks so much for your help

-coralie

Code


template<typename T>
class Vector3
{
public:
Vector3() : x(T(0)), y(T(0)), z(T(0)) {}
Vector3( T xx ) : x(xx), y(xx), z(xx) {}
Vector3( T xx, T yy, T zz ) : x(xx), y(yy), z(zz) {}
friend std::eek:stream & operator << ( std::eek:stream &os, const
Vector3<T> &v )
{
os << v.x << ", " << v.y << ", " << v.z;
return os;
}
T x, y, z;
};


template<typename T>
class Point3
{
public:
Point3() : x(T(0)), y(T(0)), z(T(0)) {}
Point3( T xx ) : x(xx), y(xx), z(xx) {}
Point3( T xx, T yy, T zz ) : x(xx), y(yy), z(zz) {}
Vector3<T> operator - ( const Point3 &p ) const
{ return Vector3<T>( x - p.x, y - p.y, z - p.z ); }
friend std::eek:stream & operator << ( std::eek:stream &os, const Point3<T>
&pt )
{
os << pt.x << ", " << pt.y << ", " << pt.z;
return os;
}
//Vector3<T> operator - ( const Point3<T> &p ) const
//{
// return Vector3<T>( x - p.x, y - p.y, z - p.z );
//}
T x, y, z;
};

template<typename T>
class Normal3
{
public:
Normal3() : x(T(0)), y(T(0)), z(T(0)) {}
Normal3( T xx ) : x(xx), y(xx), z(xx) {}
Normal3( T xx, T yy, T zz ) : x(xx), y(yy), z(zz) {}
friend std::eek:stream & operator << ( std::eek:stream &os, const
Normal3<T> &n )
{
os << n.x << ", " << n.y << ", " << n.z;
return os;
}
T x, y, z;

};

template<typename T>
void normalize( Vector3<T> &v )
{
T len2 = v.x * v.x + v.y * v.y + v.z * v.z;
if ( len2 > 0 ) {
T invLen = 1 / sqrt( len2 );
v.x *= invLen, v.y *= invLen, v.z *= invLen;
}
}

template<typename T>
Vector3<T> cross( const Vector3<T> &va, const Vector3<T> &vb )
{
return Vector3<T>(
va.y * vb.z - va.z * vb.y,
va.z * vb.x - va.x * vb.z,
va.x * vb.y - va.y * vb.x );
}

template<typename T>
Normal3<T> cross( const Vector3<T> &va, const Vector3<T> &vb )
{
return Normal3<T>(
va.y * vb.z - va.z * vb.y,
va.z * vb.x - va.x * vb.z,
va.x * vb.y - va.y * vb.x );
}

//// COMPLAINS

Vector3f edge1 = vert1 - vert0;
Vector3f edge2 = vert2 - vert0;
Vector3f pvec = cross( dir, edge2 );
 
Ad

Advertisements

P

Pavel

mast4as said:
Hi everyone

I have 2 problems related to the same code: one is compile problem
which I am not to sure to solve and the other one is to figure out a
better solution to get cleaner more elegant code. I have 2 classes
normal3 and vector3 which are in essence almost identical. The reason
why I separate them is because in CG they are not transformed the
same. Anyway this is not C++ related... But it's important to separate
them anyway. Now Vector3 and Nomal3 are in essence vector so I shall
be able to do things with them such as dot or cross product or
normalizing them. Because I wasn't able to come up with a better way I
first created 2 classes and then wrote 2 functions for the cross
products which both take 2 vector3 as parameters. But one returns a
vector and the other returns a normal. But when I try to compile ...
the compiler stops on this code (full code at the bottom of the post):

Vector3f edge1 = vert1 - vert0;
Vector3f edge2 = vert2 - vert0;
Vector3f pvec = cross( dir, edge2 );

It doesn't make sense to me because it was quite clear in that case
that cross should return a vector since the object on the left of the
equal sign is a vector ? So why does it say:
C++ (as of now) does not resolve an overloaded function based on a context like
this but only on argument. It is not clear from your code what is `dir' type. It
should be Vector3f or a reference to it for the function you want to get called.
xxxx.cppp: In function ‘int xxxxx(const Point3f&, const Vector3f&,
const Point3f&, const Point3f&, const Point3f&, float&, float&,
float&)’:
xxxxx.cpp:277: error: call of overloaded ‘cross(const Vector3<float>&,
Vector3f&)’ is ambiguous

So my first question is how can I remove this error ? (and it would be
great if I could understand what I am doing wrong). Could be that I
use templated classes ?

//////////////

The second question is more a C++ design/architecture one. And it
would be fantastic is anyone could tell me what's the best way of
solving this problem in C++. This seems out of the scope of my
comprehension right now but would really love to progress on this and
come up with a better solution:

As I said in the beginning Vector and Normal share almost all the same
code. The difference is how they are transformed by matrices. So I
don't mind creating two classes for them but what bugs me is that I
have to duplicate all the code... So what I would like to do is to
come with a solution where I can write the code for functions such as
cross, normalize and dot only once and then later do things such as:

Normal3f N = cross( Vector3f( 1, 0 , 0 ), Vector3f( 0, 1, 0 ) );
A function like

template<typename NorV3>
NorV3 cross( const NorV3 &va, const NorV3 &vb )
{
return NorV3(
va.y * vb.z - va.z * vb.y,
va.z * vb.x - va.x * vb.z,
va.x * vb.y - va.y * vb.x );
}

should work for both Normal3 and Vector3.

If you want to allow cross-products of Vector to Normal, you would need to
decide what should be the type of the result. For example, if you want the type
of the result to match the type of the first parameter, you could try this:

template<typename T1, typename T2>
T1 cross( const T1 &va, const T2 &vb )
{
return T1(
va.y * vb.z - va.z * vb.y,
va.z * vb.x - va.x * vb.z,
va.x * vb.y - va.y * vb.x );
}
 
P

Pavel

mast4as said:
Hi everyone

I have 2 problems related to the same code: one is compile problem
which I am not to sure to solve and the other one is to figure out a
better solution to get cleaner more elegant code. I have 2 classes
normal3 and vector3 which are in essence almost identical. The reason
why I separate them is because in CG they are not transformed the
same. Anyway this is not C++ related... But it's important to separate
them anyway. Now Vector3 and Nomal3 are in essence vector so I shall
be able to do things with them such as dot or cross product or
normalizing them. Because I wasn't able to come up with a better way I
first created 2 classes and then wrote 2 functions for the cross
products which both take 2 vector3 as parameters. But one returns a
vector and the other returns a normal. But when I try to compile ...
the compiler stops on this code (full code at the bottom of the post):

Vector3f edge1 = vert1 - vert0;
Vector3f edge2 = vert2 - vert0;
Vector3f pvec = cross( dir, edge2 );

It doesn't make sense to me because it was quite clear in that case
that cross should return a vector since the object on the left of the
equal sign is a vector ? So why does it say:
C++ (as of now) does not resolve an overloaded function based on a context like
this but only on argument. It is not clear from your code what is `dir' type. It
should be Vector3f or a reference to it for the function you want to get called.
xxxx.cppp: In function ‘int xxxxx(const Point3f&, const Vector3f&,
const Point3f&, const Point3f&, const Point3f&, float&, float&,
float&)’:
xxxxx.cpp:277: error: call of overloaded ‘cross(const Vector3<float>&,
Vector3f&)’ is ambiguous

So my first question is how can I remove this error ? (and it would be
great if I could understand what I am doing wrong). Could be that I
use templated classes ?

//////////////

The second question is more a C++ design/architecture one. And it
would be fantastic is anyone could tell me what's the best way of
solving this problem in C++. This seems out of the scope of my
comprehension right now but would really love to progress on this and
come up with a better solution:

As I said in the beginning Vector and Normal share almost all the same
code. The difference is how they are transformed by matrices. So I
don't mind creating two classes for them but what bugs me is that I
have to duplicate all the code... So what I would like to do is to
come with a solution where I can write the code for functions such as
cross, normalize and dot only once and then later do things such as:

Normal3f N = cross( Vector3f( 1, 0 , 0 ), Vector3f( 0, 1, 0 ) );
try
template<typename T1, typename T2, typename TR=T1 >
TR cross( const T1 &va, const T2 &vb )
{
return TR(
va.y * vb.z - va.z * vb.y,
va.z * vb.x - va.x * vb.z,
va.x * vb.y - va.y * vb.x );
}

You can call then

N = cross<Vector3f, Vector3f, Normal3f>(Vector3f(1,0,0), Vector3f(0,1,0));

You will also be able to call

Vector3f v = cross(Vector3f(1,0,0), Normal3f(0,1,0));

or

Vector3f v = cross(Vector3f(1,0,0), Vector3f(0,1,0));
 
Ad

Advertisements

M

mast4as

Hi Pavel

Thank you very much for your answer... Sorry that I forgot copy all
the needed code. dir is a Vector3f indeed here is the code. So from
what you say should it work then ? What I understand from what you
wrote is that C++ figures out the function to be called based on
arguments but not on the returned value ? I would imagine it would
look at the signature of the function which is wither Normal
cross( vector vector ) or Vector cross( Vector Vector ) and use the
right one based on the arguments and the type of the returned value
requested ?!!! No ?

-c

int xxxxxxx(
const Point3f &orig, const Vector3f &dir,
const Point3f &vert0, const Point3f &vert1, const Point3f &vert2,
float &t, float &u, float &v )
{
Vector3f edge1 = vert1 - vert0;
Vector3f edge2 = vert2 - vert0;
Vector3f pvec = cross( dir, edge2 ); <<<< FAILS HERE
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top