Attempting to specialize a single method in a templated class

Started by
4 comments, last by Julian90 16 years, 10 months ago


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?

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

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);
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).

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

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);};
ToohrVyk, that seemed to work and kept most of the clutter I was trying to avoid down. Thanks.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

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>::typefoo<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>::typebar2(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 }; };

This topic is closed to new replies.

Advertisement