Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problem with templated constructor

Started by Mantear Jan 13, 2007 at 8:22 AM 4 replies 450+ views
Original Post
Mantear
Mantear
Greetings! Could someone please point out to me why the following code snippet does not work?
class Text
{
public:
   Text();
   template <typename T> Text (T Value)
   {
      Text();
      SetText(value);
   }
   ~Text();

   void SetText(std::string value);
   void SetText(int value);
   void SetText(unsigned int value);
   void SetText(float value);
   //... etc ...

private:
   unsigned char m_TextColor[4];
}

Text::Text()
{
   m_TextColor[0] = 0;
   m_TextColor[1] = 0;
   m_TextColor[2] = 0;
   m_TextColor[3] = 255;
}
When I call the templated constructor, which in turn calls the void parameter constructor, the m_TextColor variable remains un-initialized. I stepped through with the debugger. The templated constructor called the void parameter constructor, which does set the m_TextColor. As soon as I returned from the void parameter constructor back into the templated version, the m_TextColor variable switched back to being un-initialized. Why doesn't this work?
mikeman
mikeman
This problem is not about templates, but about a constructor that tries to call another constructor of the same class. It can't be done. Calling "Text()" does not invoke the constructor for the current instance, it just creates a temporary object of class Text. See this.
Mantear
Mantear
So creating a private initialization method is the best route to take?
Thanks!
dmail
dmail
Why not just omit the call to the constructor inside the template constructor and then it will call the correct member function or generate an error if you have not defined a correct function to be called. In fact this what is happening already and the nested constructor just creates a temp which is destroyed when it goes out of scope. There is a typo in your code "Value" and "value".
jflanglois
jflanglois
By the way, what do the SetText functions do, exactly?
Zahlman
Zahlman
Quote:
Original post by Mantear
So creating a private initialization method is the best route to take?
Thanks!


I would normally do it by an initialization list, repeating the stuff in both lists. Of course, you can't initialize array contents like that. There is another trick, though, which is to make use of (abuse, in the general case; but here there is a meaningful way) inheritance or composition. You can also simplify array-initializations by copying data from a "prototype" array, and those multiple SetText functions smell very suspicious to me (like you're missing an opportunity to use std::stringstream to do your heavy lifting).

You end up with something like (not tested):

static char BLACK[4] = { 0, 0, 0, 255 };class TextColor {  unsigned char m_col[4];  public:  TextColor(const char* data) { std::copy(data, data + 4, m_col); }};class Text {  public:  Text(const char* data = BLACK) : m_color(data) {}  // FFS, pass complex types by const reference  template <typename T> Text(const T& Value, const char* data = BLACK) : m_color(data) {    SetText(value);  }  // I highly doubt you need a custom destructor.  template <typename T> void SetText(const T& value) {    std::stringstream ss;    ss << value;    m_text = ss.str();  }  private:  TextColor m_color;  std::string m_text;}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.