Jump to content


Your thoughts on non-type template parameters

c++

4 replies to this topic

#1 TheNut

    Senior Member

  • Moderators
  • 1699 posts
  • LocationThornhill, ON

Posted 25 January 2012 - 05:46 PM

I am implementing an observable property class used for data binding purposes similar to data binding available in WPF. Before I move on, let me show you a quick code snippet of this property class.

// Note, for brevity purposes the notification logic was stripped
template<class T, const String &Name>
class Property
{
	 private:
		  T mValue;

	 public:
		  Property () {}
		  Property (const T &value) { mValue = value; }
		  Property (const Property<T, Name> &value) { *this = value; }
		  virtual ~Property () {}

		  virtual T & operator = (const T &value) { mValue = value; return mValue; }
		  virtual Property<T, Name> & operator = (const Property<T, Name> &value) { mValue = value.mValue; return *this; }

		  operator T () const { return mValue; }

		  const String &GetName () const { return Name; }
};

// Example code using the above property class

extern const String MyPropertyName = "MyProperty";
int main (int argc, char **argv)
{
	 Property<int, MyPropertyName> MyProperty;
	 MyProperty = 100;
	 printf("%d\n", (int)MyProperty);

	 return 0;
}

As you can see, a simple class with a template type can sufficiently handle properties; however I also need to include the property name with the property object. As you can see I am using a non-type template parameter to pass in the property name. I thought about passing the name as a parameter in the constructor, but it would add an extra step. I'm trying to minimize the amount of boilerplate coding, but at the same time I don't want to sway towards "bad programming" practices. I never had a need to use non-type template parameters before and so I'm cautious about swaying in that direction. I'd like to hear your feedback on this and whether or not you think it could be done better / differently, but still try to minimize bloat. When you have to create hundreds of properties and deal with bindings, it can become a maintenance nightmare.
http://www.nutty.ca - Being a nut has its advantages.

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 5306 posts
  • LocationBellevue, WA

Posted 25 January 2012 - 06:18 PM

Hmm. I'm skeptical. The issue with doing it this way is you generate a new copy of the code for Property for each name you use. That may not be a big deal since the Property class looks like all the methods will probably get inlined. But, for instance, you can't write a function that works on all int properties. Well, you can by templatizing it on the name, but then you'll get a new copy of that function for each name, so you get a bunch of code bloat. Nor can you make an array of properties, or even just int properties, unless they all have the same name. On the other hand, having the name be a field in the Property class would increase the data size, while having it be a template parameter means these references are resolved at compile time and never stored at runtime. On balance I'd probably lean toward having the name be a field, personally. The difficulties in writing generic functions that work on many properties tip the balance for me.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 TheNut

    Senior Member

  • Moderators
  • 1699 posts
  • LocationThornhill, ON

Posted 25 January 2012 - 08:32 PM

Yeah, I jumped the gun here. Looks like I'll stick to the field / constructor approach as that's what I am really aiming for (runtime checks vs compile time). A little more typing, but oh well.
http://www.nutty.ca - Being a nut has its advantages.

#4 }:+()___ (Smile)

    Member

  • Members
  • PipPipPip
  • 169 posts

Posted 26 January 2012 - 10:17 AM

I think approach with non-type parameters is quite good except one thing: virtual functions add additional pointer field into Property class and spawn virtual table and function bodies for every property name. If you really need virtual functionality, you can achieve similar effect with templates:

template<typename D> class Base
{
	int virtual_function()
	{
		return static_cast<D *>(this)->virtual_function();
	}
};

class Derived : public Base<Derived>
{
	int virtual_function()
	{
		return 1234;
	}
};

template<typename D> int run_virtual_function(Base<D> *ptr)
{
	return ptr->virtual_function();
}

Sorry my broken english!

#5 .oisyn

    DevMaster Staff

  • Moderators
  • 1842 posts

Posted 27 January 2012 - 11:52 AM

That still has the requirement that *all* functions that need to handle your types in a generic way are templatized.

Of course, there simply is a middle ground

template<class T> class IProperty
{
public:
	virtual const String & GetName() const = 0;
};

template<class T, const String & S> class Property : public IProperty<T>
{
public:
	const String & GetName() const { return S; }
};

C++ addict
-
Currently working on: the 3D engine for Tomb Raider.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users