Recommended Posts

Endar    668
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 on other sites
Wavarian    850
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);

Share on other sites
stylin    758

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 on other sites
Spoonbender    1258
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 on other sites
stylin    758
Quote:
 Original post by SpoonbenderHaven'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 versionsome_class sc2 = static_cast< some_class > ( 3.0f );      // uses float version

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

Share on other sites
Quote:
 Original post by stylinSo, 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 versionsome_class sc2 = static_cast< some_class > ( 3.0f ); // uses float versionAnything 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 on other sites
stylin    758
Quote:
Original post by Erzengeldeslichtes
Quote:
 Original post by stylinSo, 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 versionsome_class sc2 = static_cast< some_class > ( 3.0f ); // uses float versionAnything 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.

Create an account

Register a new account