Jump to content
  • Advertisement
Sign in to follow this  

template specialization problem

This topic is 3859 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 have a function I want to work on several types like int, double, std::string, ..., and also on any class that inherits from "Foo". It must have the same name and order of parameters in all cases to make it easy to use. For making it work on int, double and std::string, I make it a template function. Now I want to have a specialized version for anything that inherits from "Foo", because there needs to be done different stuff in this case. However it seems like it doesn't work, it's as if template specialization looks only at the exact type, not at the type a class inherits from. Is there a way to get my thing to work without having to write a separate version for each type (int, double, std::string)?

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by ToohrVyk
Use overloading instead of specialization for Foo&. See also GOTW.


But then I have to type the same code for each of int, double, std::string, and so on? I'd call that code duplication, which I find evil :(

EDIT: oh wait, you can combine overloading AND templates? Woot!

EDIT2:

No, still doesn't work, it seems still to match only exact types and doesn't look at types you inherited from :(

If I made the Foo version take a Foo*, it used the template version and converted my pointer to a boolean, instead of using the foo version...

Share this post


Link to post
Share on other sites
I had exactly the same problem and came to no real solution... I wanted to write a generic hash function that would invoke a "Hash"-Method on all objects that inherit from a specific base class while it would return hash values for primitive types such as int, float, double, etc. based on some simple algebra.
However, I couldn't get it to correctly distinguish between types (Even if I specialized the function template to accept only Object* or Object&, it would always call the int-version of the function). I ended up putting the code that invokes the "Hash"-method into the generic version of the function which worked okay:


template <class T>
uint Hash(const T& tObject)
{
return tObject.Hash();
}

template <>
uint Hash<int>(const int& iInt)
{
return static_cast<uint>(iInt);
}


Since I need to pass in the object as a reference, I had to pass in the int as a reference as well (otherwise it wouldn't consider it a specialization of the template).

Share this post


Link to post
Share on other sites
Oops, you are right.

You could consider using boost;

template<typename T>
boost::disable_if< boost::is_base_of<Foo,T> >::type
your_function(const T &)
{
// Basic version for int/etc...
}

void
your_function(const Foo&)
{
// Foo-version of your function
}


Alternately, you could just reimplement this small bit yourself to further restrict the application of your function.


template<typename T> struct supports_my_function {};
#define SUPPORT(T) template<> struct supports_my_function<T> { typedef void type; };
SUPPORT(int)
SUPPORT(float)
SUPPORT(bool)
SUPPORT(std::string)
#undef SUPPORT

template<typename T>
supports_my_function<T>::type
your_function(const T &)
{
// Basic version for int/etc...
}

void
your_function(const Foo&)
{
// Foo-version of your function
}

Share this post


Link to post
Share on other sites
How about:


namespace detail
{
template<bool IsFoo>
struct discombobulate_impl
{
template<typename T>
static void do_it(const T &x)
{
// the generic code
}
};

template<>
struct discombobulate_impl<true>
{
static void do_it(const Foo &x)
{
// the code for a Foo object
}
};

}

template<typename T>
void discombobulate(const T &x)
{
const bool isFoo = boost::is_base_of<Foo, T>::value;
detail::discombobulate_impl<isFoo>::do_it(x);
}




Edit: forgot static keywords! Fixed now.

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!