C++ says that these are ambiguous...

M

mast2as

Hello, I have 2 classes *as an example* Point & Color and friend
operator * in the class Point is defined in such a way that it is
possible to do something like that Point p = Point( 1.0 ) * Color( 2.0
);

// in point.hpp
class Color;

class Point {
public:
float x, r, z;
Point( float xx ) : x( xx ), y( xx ), z( xx ) {}
friend Point operator * ( const Point &p, const Color &c )
{ return Point( p.x * c.x ); }
};

//in color.hpp
class Vector;
class Color {
public:
float r, g, b;
Point( float xx ) : r( xx ), g( xx ), b( xx ) {}
};

// so that line somwhere in the code works
Point p = Point( 1.0 ) * Color( 2.0 );

And it compile fine.

Now I tried to provide the Point vector with a constuctor where the
argument that is passed is a Color and rewrote the friend operator * to
take advantage of that:

class Point {
...
Point( const Color& c ) : x( c.r ), y( c.g ), z( c.b ) {}
Point operator * ( const Point& p ) { return Point( x * p.x, y * p.y,
z * p.z ); }
friend Point operator * ( const Point &p, const Color &c )
{ return p * Point( c ); }
};

But when I compile I get the following error message:

error: ISO C++ says that these are ambiguous, even though the worst
conversion for the first is better than the worst conversion for the
second:
../math/point.hpp:90: note: candidate 1: Point<float> operator*(const
Point<float>&, const Color<float>&)
../math/point.hpp:55: note: candidate 2: Point<T>
Point<T>::eek:perator*(const Point<T>&) [with T = float]

Basically the compile from what I understand the compiler doesn't know
if it needs to convert the color into a point and use the * operator or
to use the friend * operator and keep the right hand side argument as a
Color.

Could someone tell me what is the best way of doing that please ? Just
using constructors that allows explicit conversion of different types (
Color to Point ) and use the operator of the Point class, or not having
any explicit conversion in the Point class and only use the friend * (
Point, Color ) operator.

Thanks -
 
L

LR

Hello, I have 2 classes *as an example* Point & Color and friend
operator * in the class Point is defined in such a way that it is
possible to do something like that Point p = Point( 1.0 ) * Color( 2.0
);

// in point.hpp
class Color;

class Point {
public:
float x, r, z;
Point( float xx ) : x( xx ), y( xx ), z( xx ) {}
friend Point operator * ( const Point &p, const Color &c )
{ return Point( p.x * c.x ); }
};

//in color.hpp
class Vector;
class Color {
public:
float r, g, b;
Point( float xx ) : r( xx ), g( xx ), b( xx ) {}
};

// so that line somwhere in the code works
Point p = Point( 1.0 ) * Color( 2.0 );

And it compile fine.

I very much doubt that the above will compile fine. One example, x is
not a member of Color. Another, you seem to have a ctor for Point as a
member of Color.
Now I tried to provide the Point vector

What is the Point vector? Are you trying to create a
> with a constuctor where the
argument that is passed is a Color and rewrote the friend operator * to
take advantage of that:

class Point {
...
Point( const Color& c ) : x( c.r ), y( c.g ), z( c.b ) {}
Point operator * ( const Point& p ) { return Point( x * p.x, y * p.y,
z * p.z ); }
friend Point operator * ( const Point &p, const Color &c )
{ return p * Point( c ); }
};

But when I compile I get the following error message:

error: ISO C++ says that these are ambiguous, even though the worst
conversion for the first is better than the worst conversion for the
second:
./math/point.hpp:90: note: candidate 1: Point<float> operator*(const
Point<float>&, const Color<float>&)
./math/point.hpp:55: note: candidate 2: Point<T>
Point<T>::eek:perator*(const Point<T>&) [with T = float]

Are these error messages being produced for template classes? Well, I'm
not exactly sure what's wrong, but you may be able to fix the problem by
changing this:

Point operator * ( const Point& p ) {
return Point( x * p.x, y * p.y, z * p.z );
}

to this:

friend Point operator*(const Point &p1, const Point &p2) { ... }


Basically the compile from what I understand the compiler doesn't know
if it needs to convert the color into a point and use the * operator or
to use the friend * operator and keep the right hand side argument as a
Color.

Could someone tell me what is the best way of doing that please ? Just
using constructors that allows explicit conversion of different types (
Color to Point ) and use the operator of the Point class, or not having
any explicit conversion in the Point class and only use the friend * (
Point, Color ) operator.

I think this question may be a little bit beyond me, but I think the
answer will be, It Depends.

What will be the effect of having ctors that convert? Will that have
some bad unforeseen consequences later?

How tightly coupled are Color and Point?
Why are they two seperate classes?

Would you be better off having a function:
Point PointFromColor(const Color &c) { return Point(....); }
and then..
Point p = point * PointFromColor(color);



What is it that you are trying to communicate to someone who might read
your code?

LR
 
S

Salt_Peter

Hello, I have 2 classes *as an example* Point & Color and friend
operator * in the class Point is defined in such a way that it is
possible to do something like that Point p = Point( 1.0 ) * Color( 2.0
);

That doesn't make sense. A point is a Point and a Color is a Color. Are
you trying to create a derived ColouredPoint class? If you are then
surely Color is an attribute of the ColouredPoint. A Color is_not a
Point.

Could someone tell me what is the best way of doing that please ? Just
using constructors that allows explicit conversion of different types (
Color to Point ) and use the operator of the Point class, or not having
any explicit conversion in the Point class and only use the friend * (
Point, Color ) operator.

Take a look at the following and then explain what you are trying to
get, cause i still don't follow the question.

// proj_color.cpp : Defines the entry point for the console
application.
//

#include <iostream>
#include <ostream>
#include <vector>

class Point
{
int x, y, z;
public:
Point() : x(0), y(0), z(0) { } // default ctor
Point( int x_, int y_, int z_ ) : x(x_), y(y_), z(z_) { }
virtual ~Point() { }
};

class Color
{
float r, g, b;
public:
Color( ) : r(0), g(0), b(0) { } // default ctor
Color( float r_, float g_, float b_ ) : r(r_), g(g_), b(b_) { }
~Color() { }
/* friend op<< */
friend std::eek:stream& operator<<(std::eek:stream& os, const Color& r_c)
{
os << "r = " << r_c.r;
os << " g = " << r_c.g;
os << " b = " << r_c.b;
return os << "\n";
}
};

class ColoredPoint : public Point
{
Color color; // composition
public:
ColoredPoint() : color() { } // default ctor
ColoredPoint( int x_, int y_, int z_, float r_, float g_, float b_ )
: Point(x_, y_, z_), color(r_, g_, b_) { }
/* member functions */
Color getColor() const { return color; }
};

int main()
{
std::vector< ColoredPoint* > vpoints;

vpoints.push_back( new ColoredPoint );
vpoints.push_back( new ColoredPoint( 1,1,1,128.0,128.0,128.0) );

Color color_origin = vpoints[0]->getColor(); // default color
std::cout << "color_origin is " << color_origin;
Color color_test = vpoints[1]->getColor(); // medium gray
std::cout << "color_test is " << color_test;

typedef std::vector< ColoredPoint* >::iterator VIter;
VIter iter = vpoints.begin();
for( iter; iter != vpoints.end(); ++iter )
{
delete *iter;
}
return 0;
}

/*
color_origin is r = 0 g = 0 b = 0
color_test is r = 128 g = 128 b = 128
*/
 
J

Jerry Coffin

[ ... ]
That doesn't make sense. A point is a Point and a Color is a Color.

Depending on the situation, it's often useful to think of a color as a
point in a 3D color-space. When writing things like shaders for 3D
hardware, you often want to treat the two interchangeably as well.

At the same time, you're right that derivation is probably a problem
here. You can't substitute any random point in all situations that call
for a color or vice versa.
 

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

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top