C++ says that these are ambiguous...

Discussion in 'C++' started by mast2as@yahoo.com, Aug 31, 2006.

  1. Guest

    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 -
    , Aug 31, 2006
    #1
    1. Advertising

  2. LR Guest

    wrote:

    > 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
    std::vector<Point>? Are you refering to your class Vector? If so, what
    is it?

    > 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
    LR, Aug 31, 2006
    #2
    1. Advertising

  3. Salt_Peter Guest

    wrote:
    > 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.

    <clipped>
    > 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
    */
    Salt_Peter, Aug 31, 2006
    #3
  4. Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > 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.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Sep 2, 2006
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. walala
    Replies:
    3
    Views:
    4,134
    Renaud Pacalet
    Oct 3, 2003
  2. Jason Shohet
    Replies:
    1
    Views:
    462
    William F. Robertson, Jr.
    Aug 1, 2003
  3. KK
    Replies:
    1
    Views:
    410
    thoean
    Sep 8, 2003
  4. Alex Vinokur
    Replies:
    4
    Views:
    3,032
    Peter Koch Larsen
    Nov 26, 2004
  5. TheFlyingDutchman
    Replies:
    5
    Views:
    1,786
    Johannes Schaub
    May 13, 2011
Loading...

Share This Page