Jump to content
  • Advertisement
Sign in to follow this  
soconne

C++ templates and conditional code generation

This topic is 3615 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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!)

Share this post


Link to post
Share on other sites
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);

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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) {

}
};

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!