Jump to content
  • Advertisement
Sign in to follow this  
Rattrap

Attempting to specialize a single method in a templated class

This topic is 4057 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 <typename T, bool flag>
class Foo
{
    public:
        typedef std::vector<T> array_type;

        static void bar1(array_type& output, const array_type& input1, const array_type& input2);
        static void bar2(array_type& output, const array_type& input1, const array_type& input2);
};

template <typename T, bool flag>
void Foo<T, flag>::bar1(array_type& output, const array_type& input1, const array_type& input2)
{
    // Do stuff
}

template <typename T, bool flag>
void Foo<T, flag>::bar2(array_type& output, const array_type& input1, const array_type& input2)
{
    // Do stuff
}

template <bool flag>
void Foo<bool, flag>::bar2(array_type& output, const array_type& input1, const array_type& input2)
{
    // Do bool specific stuff
}



I know this isn't completely right, but this is what I'm going for. I want to know if it is possible to write a single specialized case for a method. In this case, in bar2 I need to supply a specialization for when T is a bool. But I don't need to do the same for bar1. (I hope that makes sense). Is there a way to do this, espeically without a complete class specialization?

Share this post


Link to post
Share on other sites
Advertisement
Your methods are static.

Hence: they don't need to be in a class, put them in namespace.


namespace foo {

template < bool flag >
static void test( int x )
{

}

template<>
static void test<true>( int x)
{

}

}

...

foo::test<false>(1);
foo::test<true>(1);


Share this post


Link to post
Share on other sites
Your example doesn't work, because you only use a single template argument. Mine has two, which then introduces partial specialization, which if applied to your example, is illegal. I want the flag to carry over, while only specializing the T/bool part. In your example, I would have to make 2 seperate versions of the same code, because I would also have to specialize both versions of the flag.

so

template <>
void bar<bool, true>(...) {}

and

template <>
void bar<bool, false>(...) {}

which I'm trying to avoid rewriting this thing most than I have too.

Also the advantage of having it in the class is the typedef, which auto generated the parameters (at least it does it a lot cleaner that std::vector<T> everywhere).

Share this post


Link to post
Share on other sites
template <typename T, bool flag>
struct bar1impl {
static void do(std::vector<T>& output, const std::vector<T>& input1, const std::vector<T>& input2)
{ /* Default implementation */ }
};

template<bool flag>
struct bar1impl<bool,flag> {
static void do(std::vector<T>& output, const std::vector<T>& input1, const std::vector<T>& input2)
{ /* Specialized implementation */ }
};

template <typename T, bool flag>
class Foo
{
public:
typedef std::vector<T> array_type;

static void bar1(array_type& output, const array_type& input1, const array_type& input2)
{ bar1impl<T,flag>::do(output,input1,input2); }
static void bar2(array_type& output, const array_type& input1, const array_type& input2);
};

Share this post


Link to post
Share on other sites
ToohrVyk, that seemed to work and kept most of the clutter I was trying to avoid down. Thanks.

Share this post


Link to post
Share on other sites
An Alternative:


#include <boost/type_traits/is_same.hpp>
#include <boost/enable_if.hpp>

template<typename T, bool flag>
struct foo
{
typedef std::vector<T> array_type;

static void bar1(array_type& output, const array_type& input1, const array_type& input2);
static typename boost::enable_if<boost::is_same<T, bool>, void>::type
bar2(array_type& output, const array_type& input1, const array_type& input2);
static typename boost::disable_if<boost::is_same<T, bool>, void>::type
bar2(array_type& output, const array_type& input1, const array_type& input2);
};


template<typename T, bool flag>
static void foo<T, flag>::bar1(array_type& output, const array_type& input1, const array_type& input2)
{
// implement bar1
}

template<typename T, bool flag>
static typename boost::enable_if<boost::is_same<T, bool>, void>::type
foo<T, flag>::bar2(array_type& output, const array_type& input1, const array_type& input2)
{
// implement bar2 for bool's
}

static typename boost::disable_if<boost::is_same<T, bool>, void>::type
bar2(array_type& output, const array_type& input1, const array_type& input2)
{
// implement bar2 for non-bools
}



This has the advantages that bar2<bool, flag> doesn't have to have the same parameters as bar2<T, flag> but the disadvantage of relying on boost which may not be an option if this is for work and there are policies against it. The stuff used from boost is fairly easy to implement though, something along the lines of the following would work.


template<bool C, typename R>
struct enable_if_impl
{
typedef R type;
};

template<typename T>
struct enable_if_impl<false, R>
{ };

template<typename T, typename R>
struct enable_if : enable_if_impl<T::value, R>
{ };

template<typename T, typename R>
struct disable_if : enable_if_impl<!T::value, R>
{ };

template<typename T1, typename T2>
struct is_same
{ enum { value = false }; };

template<typename T>
struct is_same<T, T>
{ enum { value = true }; };

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!