C++ templates and conditional code generation

Started by
11 comments, last by Nyarlath 15 years, 9 months ago
I'm have a class template and I would like to test whether one of the type parameters is a pointer or not.

template <class T>
class Test {
    if T is a pointer then generate
        void set(T* value) { }
    else
        void set(const T& value) { }
};


Is there a way to do this? I've thought about attempting it using template specialization, but how do you determine within the template, if a parameter is a pointer or not? **EDIT** I've come up with the following way using template specialization but its kind of ugly.

template <class T, bool isPointer=false>
class Test {
public:
	T m_var;
};

template <class T>
class Test<T, true> {
public:
	T* m_var;
};

Is there a better way?
Author Freeworld3Dhttp://www.freeworld3d.org
Advertisement
template <typename T>class Test{    typedef typename boost::mpl::if_<boost::is_pointer<T>::value, T*, const T&>::type parameter_type;    void set(parameter_type value)    {    }};


Namespaces might be wrong here or there, but that's what you're looking for.

Edit: Removed 'typename' before boost::is_pointer<T>::value (not a type!)
[ search: google ][ programming: msdn | boost | opengl ][ languages: nihongo ]
If you don't want to use boost, this should work:

template <typename T>class Kitten{public:   void set(const T& t) { cout << "const ref version: " << t << "\n"; }};template <typename T>class Kitten <T*>{public:   void set(T *t) { cout << "pointer version: " << *t << "\n"; }};


then:

Kitten <int> whiskers;whiskers.set(5);Kitten <int *> fluffy;int value = 10;fluffy.set(&value);
Quote:Original post by PiNtoS
If you don't want to use boost, this should work:


Hey thanks PiNtoS. That's pretty much what I was going for.

But I also like the example _goat showed using boost. Although if at all possible I'd like not to use boost. I took a look at the boost header file containing the if_ template, it doesn't make a lot of sense, but I would ultimately like something similar to that.
Author Freeworld3Dhttp://www.freeworld3d.org
Well this is interesting. Apparently type_traits will be part of the new C++ specification.
http://www.aristeia.com/EC3E/TR1_info.html

That's going to be pretty cool.
Author Freeworld3Dhttp://www.freeworld3d.org
Well in case anybody was interested, I figured out how to implement is_pointer and fi_ using template specialization, which freakin rocks!

template <class T>struct is_pointer {		enum { value = false };	};template <class T>struct is_pointer<T*> {	enum { value = true };};template <bool condition, class T1, class T2>struct if_ { };template <class T1, class T2>struct if_<true, T1, T2> {	typedef T1 type;};template <class T1, class T2>struct if_<false, T1, T2> {	typedef T2 type;};template <typename T>class Test {public:	typedef typename if_<is_pointer<T>::value, T*, const T&>::type parameter_type;	void set(parameter_type value) {	}};
Author Freeworld3Dhttp://www.freeworld3d.org
Quote:Original post by soconne
Quote:Original post by PiNtoS
If you don't want to use boost, this should work:


Hey thanks PiNtoS. That's pretty much what I was going for.

But I also like the example _goat showed using boost. Although if at all possible I'd like not to use boost. I took a look at the boost header file containing the if_ template, it doesn't make a lot of sense, but I would ultimately like something similar to that.


Don't avoid Boost. It has a ton of extremely useful functionality. Install it, and use the bits you find convenient. There's usually no reason not to.

However, in this particular case, I'd say using boost's type_traits is overkill. As shown above, it's simple enough to make a template specialization for pointers.

But seriously, "I'd like not to use boost" is just silly. You might as well say you'd rather avoid functions, or loops. C++ without boost is just silly. [grin]
It's one of the few things that make C++ bearable.
Yes I would definitely agree. Its just that I have not grown accustomed to boost's syntax and like you said, I only really need a single header file from it for type_traits.
Author Freeworld3Dhttp://www.freeworld3d.org
I've run into another slight problem. When I declare a property that's a pointer, I have no direct access to the -> operator. For instance:

class Test {
public:
property<MyClass*> class;
};

Test t;
t.class-> // this throws an error

Hence I have to overload the -> operator like so inside of the property template class.

ValueType operator->() const {
return getter();
}

ValueType is MyClass* in this case. My problems is that I don't want this function generated for a non-pointer type. So declaring property<MyClass> would not generate it. But I also do not want to have template specialization. Is there a way to accomplish this similar to the type traits method I used above for function parameters?

Hence, I want the overloaded operator -> function generated for a pointer type property, but not for a non-pointer type property, and I want the compile time condition within a single property class.
Author Freeworld3Dhttp://www.freeworld3d.org
Quote:Original post by soconne
I've run into another slight problem. When I declare a property that's a pointer, I have no direct access to the -> operator. For instance:[...]
If you want Class<T> and Class<T*> to be different, you want template specialization as PiNtoS showed. If there is a lot of shared code between the various specializations, make a non-specialized property_base class that all the specialized property templates derive from.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

This topic is closed to new replies.

Advertisement