Jump to content
  • Advertisement
Sign in to follow this  
Endar

template specialisation

This topic is 4615 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

Template specialisation is basically when you write a function for specific behaviour for a type, right? I have a function that should only be called for the primitive types, primitive pointer types and std::string, std::string*. Will template specialisation be able to restrict the types used with this function to only these if I write a function for each?

Share this post


Link to post
Share on other sites
Advertisement
Two ways you could accomplish this:

Using SFINAE:
boost::enable_if if boost is available in your project - requires boost
roll your own class with enable_if like functionality - could be a significant amount of work

Using function overloading:
In a header file declare funcitons prototypes for each of the tpyes you function should be callable for. In the corresponding source file, put your template function in the anonymous namespace, then implement each function prototype as a call to the template function.

i.e.:

//hpp
void addOne(char& data);
void addOne(int& data);
void addOne(unsigned int& data);

//cpp
namespace
{
template < class T >
void addOne_impl(T& data)
{
++data;
}
}

void addOne(char& data){ addOne_impl(data); }
void addOne(int& data){ addOne_impl(data); }
void addOne(unsigned int& data){ addOne_impl(data); }


Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Template specialisation is basically when you write a function for specific behaviour for a type, right?

I have a function that should only be called for the primitive types, primitive pointer types and std::string, std::string*. Will template specialisation be able to restrict the types used with this function to only these if I write a function for each?


Why should it only be called for those types? What does it do? The whole point of templates is that you write generic code that can be used with any type that supports the operations you perform on it...

Share this post


Link to post
Share on other sites
I've created an in-engine debug console which includes support for adding the addresses of variables outside the console and being able to access them inside the console at runtime. Pretty much all the primitive types except for char.

I'm using boost::variant to store pointers to all these variables, and visitors to get and set the values on the other end of the pointers.

I am using the function as a simple way to be able to add a pointer. I just started thinking that someone else who used this (or even me, it doens't really matter, it's probably good programming practice to at least think about these things) could attempt to add something more complex than a primitive type.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Template specialisation is basically when you write a function for specific behaviour for a type, right?


Yes and no.

Templates are used when you have a general algorithm that can be applied to all data types. You can use specializations to provide a variant of the algorithm for certain data types.

You can use template specialization to do what you're proposing by having the general case throw an exception at runtime and then specialize for all your supported types.

It's better to just use function overloading, though,because that will catch misuse at compile time, which is many orders of magnitude cheaper (at least, if other people use your software).

Share this post


Link to post
Share on other sites
Sure, you could use specialized function templates for seomthing like that. You could do something like the following:

template <typename Type>
bool Foo(Type &rInst);

template <typename Type>
bool Foo(Type &rInst)
{
//If not a specialized template, not supported.
return false;
}

template <>
bool Foo(int &rInst)
{
//do work...
return true;
}

template <>
bool Foo(std::string &rInts)
{
//do work...
return true;
}



basically specialize the function for all the types you want to support, and have supported types return true. Unsupported types will call the unspecialized function and return false.

Share this post


Link to post
Share on other sites
If the code for most types is fundamentally differet, use overloads.


void foo(int);
void foo(double);
void foo(char const*);
void foo(std::string<char>);

etc.

Templates on types are useful when the code with two different types is quite similar.

If the code for most types is similar, then try:

struct not_allowed {};

struct allowed {typedef void check;};

template<typename T>
struct basic_types_only: not_allowed {};

template<> struct basic_types_only<int>: allowed {};
template<> struct basic_types_only<double>: allowed {};
template<> struct basic_types_only<std::string<char> >: allowed {};
template<> struct basic_types_only<char>: allowed {};
// etc

template<typename T>
typename basic_types_only<T>::check
do_work( T t ) {
// code goes here
}


Then calling do_work for any type that isn't in the "allowed" list will fail.

But really, with a template, you can often "let the chips fall where they may" and simply have your code try to work with every type you pass it.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!