Sign in to follow this  
Endar

Asking for trouble

Recommended Posts

Here are two of the constructors for a class I have:
/** 
 * Constructor that inits the color when given the four parts.
 * \param a Unsigned integer value from 0-255 representing the alpha value of the color.
 * \param r Unsigned integer value from 0-255 representing the red value of the color.
 * \param g Unsigned integer value from 0-255 representing the green value of the color.
 * \param b Unsigned integer value from 0-255 representing the blue value of the color.
 */
CColor(unsigned int a, unsigned int r, unsigned int g, unsigned int b)
{
	// Set the color
	set(a, r, g, b);
}

/**
 * Constructor
 * \param a Float value from 0.0f-1.0f representing the alpha value of the color.
 * \param r Float value from 0.0f-1.0f representing the red value of the color.
 * \param g Float value from 0.0f-1.0f representing the green value of the color.
 * \param b Float value from 0.0f-1.0f representing the blue value of the color.
 */
CColor(float a, float r, float g, float b)
{
	// set the color
	set(a, r, g, b);
}


Now, often when I call them, I have problems because ints are promoted to floats. Is there a way of writing the constructors so that I don't have to explcitly define where I call the functions?

Share this post


Link to post
Share on other sites
Well, here you have ambiguous function definitions. You can either change your parameter types from "unsigned int" to "int", or, you can specify which one you want to use explicitly (which you don't want to do):


CColor colorA((unsigned int)1, (unsigned int)2, (unsigned int)3, (unsigned int)4);

CColor colorB(1U, 2U, 3U, 4U);


Pick your poison :x

Share this post


Link to post
Share on other sites
Parameterize your CColor class.

EDIT: Or better yet, specialize a function template:
namespace Endar {

class color { /*...*/ };

template< typename T >
color get_color( T a, T r, T g, T b );

typedef unsigned char byte_range;
typedef float normalized_range;

template<>
color get_color( byte_range a, byte_range r, byte_range g, byte_range b ) {

// ... // code for converting 0...255 color ranges to
// whatever format color uses
return color( /*...*/ );
}

template<>
color get_color( normalized_range a, normalized_range r, normalized_range g, normalized_range b ) {

// ... // code for converting 0.0...1.0 color ranges to
// whatever format color uses
return color( /*...*/ );
}
}

int main() {

using Endar::byte_range;
using Endar::normalized_range;

// use both types of input to create colors
Endar::color color1 = Endar::get_color( byte_range(0), byte_range(63), byte_range(127), byte_range(255) );
Endar::color color2 = Endar::get_color( normalized_range(0.0), normalized_range(0.25), normalized_range(0.5), normalized_range(1.0) );

return 0;
}





[Edited by - stylin on October 24, 2005 5:43:41 AM]

Share this post


Link to post
Share on other sites
Haven't used this in ages, so I'm not 100% sure, but isn't this where you'd use the explicit keyword?

Something like

explicit CColor(unsigned int a, unsigned int r, unsigned int g, unsigned int b)
explicit CColor(float a, float r, float g, float b)

Share this post


Link to post
Share on other sites
Quote:
Original post by Spoonbender
Haven't used this in ages, so I'm not 100% sure, but isn't this where you'd use the explicit keyword?

Something like
*** Source Snippet Removed ***

The explicit keyword eliminates implicit conversions. You use it in situations where you want to limit usage. For example:

class some_class {

public:
explicit some_class( int );
some_class( float );
};
...
some_class sc1 = 3; // float version is used since there are no implicit
// conversions from int to some_class.

The above is like saying, "you can convert a float into a some_class, but in order to convert an int to a some_class you must do it explicitly."

So, you can see the problem if you make both constructors explicit; the only way to convert to a some_class from either format would be to do it explicitily:

some_class sc1 = static_cast< some_class > ( 3 ); // uses int version
some_class sc2 = static_cast< some_class > ( 3.0f ); // uses float version

Anything else won't compile because of the explicit constructors.

Share this post


Link to post
Share on other sites
Quote:
Original post by stylin
So, you can see the problem if you make both constructors explicit; the only way to convert to a some_class from either format would be to do it explicitily:

some_class sc1 = static_cast< some_class > ( 3 ); // uses int version
some_class sc2 = static_cast< some_class > ( 3.0f ); // uses float version

Anything else won't compile because of the explicit constructors.


Actually, some_class sc1(3); would compile fine, as would some_class sc1(3.0f);. You don't need to use an equal sign to initialize a variable, just as you could do some_class(int, int) and then some_class ClassInstance(3,2);. But the meat of your post is true.

Share this post


Link to post
Share on other sites
Quote:
Original post by Erzengeldeslichtes
Quote:
Original post by stylin
So, you can see the problem if you make both constructors explicit; the only way to convert to a some_class from either format would be to do it explicitily:

some_class sc1 = static_cast< some_class > ( 3 ); // uses int version
some_class sc2 = static_cast< some_class > ( 3.0f ); // uses float version

Anything else won't compile because of the explicit constructors.


Actually, some_class sc1(3); would compile fine, as would some_class sc1(3.0f);. You don't need to use an equal sign to initialize a variable, just as you could do some_class(int, int) and then some_class ClassInstance(3,2);. But the meat of your post is true.

True, and I was addressing the situations in which the explicit keyword is relavent, as it has no bearing on explicitly-called constructors. By "anything" I meant any form of copy assignment/assignment, in which implicit conversions are taking place, hence the purpose of the explicit keyword. Should have clarified - good heads up.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this