Jump to content

  • Log In with Google      Sign In   
  • Create Account


A templated cross-type copy constructor question


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 irreversible   Crossbones+   -  Reputation: 1212

Like
0Likes
Like

Posted 09 September 2012 - 06:56 AM

This question actually bears little relevance to what I'm doing, but it did make me curious.

I have a color class called IColor, which extends from an IColorBase template class like:

typedef IColorBase<float> IColor;

IColorBase is a generic base class that provides the usual constructors and operator overloading and not much else. What got me interested, though, was handling a cross-type copy constructor like:

IColor color = RGB(0, 255, 0);

RGB() is a macro that splices byte components into a DWORD. The copy constructor looks like this:

IColorBase(DWORD& clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }

My question, however, has to do with multi-type copy constructors. Let's say I also have:

typedef IColorBase<BYTE> IRGBA;

Whose copy constructor would look like this:

IColorBase(DWORD& clr) { BYTE* _c = (BYTE*)&clr; r = _c[0]; g = _c[1]; b = _c[2]; a = 255; }

Including two constructors that take the same input argument type, however, doesn't make sense without a specific type declaration. In other words, I'd need something like this:

IColorBase<float>(DWORD clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }
IColorBase<BYTE>(DWORD clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }

Which, of course, doesn't work. Is it possible to provide type-aware constructors like this or does the standard not allow it at all? After all, it's possible for assignment operators.

Sponsor:

#2 Hodgman   Moderators   -  Reputation: 27930

Like
3Likes
Like

Posted 09 September 2012 - 08:04 AM

I looks like you're looking for template specialization, and you've almost got the syntax right:
template<class T> struct Color

{

	Color(uint i);

	T r,g,b,a;

};



template<> Color<float>::Color(uint i) { r = (i&0xFF)/255.0f; }

template<> Color<ubyte>::Color(uint i) { r = (i&0xFF); }


#3 Cornstalks   Crossbones+   -  Reputation: 6966

Like
4Likes
Like

Posted 09 September 2012 - 08:10 AM

I have a color class called IColor, which extends from an IColorBase template class like:

typedef IColorBase<float> IColor;

That's not quite an "extension" ("extension" implies it inherits from IColorBase). That's just a normal "IColor is a typedef for IColorBase<float>."

RGB() is a macro that splices byte components into a DWORD. The copy constructor looks like this:

IColorBase(DWORD& clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }

That's not a copy constructor. It's just a normal constructor that takes a DWORD. Also, you should make it a const DWORD& because you can't bind a non-const reference to a temporary. Actually, you probably want to just take out the reference all together and just make it a normal DWORD. There won't be any benefit here from using a reference.

Also, I wish you made RGB() an inline function and not a macro... I hate macros. They have no respect for namespace scope or anything.

Whose copy constructor would look like this:

IColorBase(DWORD& clr) { BYTE* _c = (BYTE*)&clr; r = _c[0]; g = _c[1]; b = _c[2]; a = 255; }

Again, not a copy constructor.

Including two constructors that take the same input argument type, however, doesn't make sense without a specific type declaration. In other words, I'd need something like this:

IColorBase<float>(DWORD clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }
IColorBase<BYTE>(DWORD clr) { BYTE* _c = (BYTE*)&clr; r = _c[0] / 255.f; g = _c[1] / 255.f; b = _c[2] / 255.f; a = 1; }

Which, of course, doesn't work. Is it possible to provide type-aware constructors like this or does the standard not allow it at all? After all, it's possible for assignment operators.

Hmmm... I don't see any difference between the two? Did you intent for the constructors for IColorBase<float> and IColorBase<BYTE> to be exactly identical? Because I would've thought IColorBase<BYTE>'s constructor would've looked something like this:

IColorBase<BYTE>(DWORD clr) { BYTE* _c = (BYTE*)&clr; r = _c[0]; g = _c[1]; b = _c[2]; a = 255; }

If this is indeed what you intended, you could use a helper kind of like this:
template <typename T>
struct IColorBaseHelper;


template <>
struct IColorBaseHelper<float>
{
  static const float max = 1.0f; // You don't need min or max now, but this shows
  static const float min = 0.0f; // you that you can put useful stuff here
  static const float dword_convert = 255.0f;
};


template <>
struct IColorBaseHelper<BYTE>
{
  static const BYTE max = 255; // You don't need min or max now, but this shows
  static const BYTE min = 0;   // you that you can put useful stuff here
  static const BYTE dword_convert = 1;
};


template <typename T>
class IColorBase
{
  T r, g, b, a;

public:
  IColorBase(const DWORD clr) :
    r((clr & 0x000000ff) / IColorBaseHelper<T>::dword_convert),
    g(((clr & 0x0000ff00) >> 8) / IColorBaseHelper<T>::dword_convert),
    b(((clr & 0x00ff0000) >> 16) / IColorBaseHelper<T>::dword_convert),
    a(((clr & 0xff000000) >> 24) / IColorBaseHelper<T>::dword_convert) // Why not have RGB() set alpha to 100%?
  {
  }
};
The nice thing about this is that it doesn't require you to template-specialize the entire class, and allows you to just template-specialize the relevant part(s).

Edited by Cornstalks, 09 September 2012 - 08:16 AM.

[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#4 irreversible   Crossbones+   -  Reputation: 1212

Like
0Likes
Like

Posted 11 September 2012 - 02:13 PM

Thanks for the replies, guys! I could probably have take it myself from "template specialization", though.

Cornstalks - you're right about it not being a copy constructor. In this case the word of the law does defeat the spirit of it :)

Did you intent for the constructors for IColorBase<float> and IColorBase<BYTE> to be exactly identical?


Yeah - that's a copy-paste thing.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS