Question

I've got a template class with a template method within it, giving two template parameters T and U. The operation is quite expensive and is showing up in profiling to be a major use of CPU time. I could optimise it somewhat, but only for the case where T == U (which is fairly common), however I'm not sure on the syntax for doing this...

The class and method in question look like this:

template<typename T>class Foo
{
public:
    ...
    template<typename U>U bar()const;
};

Foo::bar is generally called from some other template code, so even if I created a separate method (e.g. "T fastBar()const") I don't know how id go about making the other template code call that version where possible...

I tried to create an explicit specialisation for T == U, but VC9 gave me errors

template<typename T>template<>T Foo<T>::bar<T>()const

error C2768: 'Foo::bar' : illegal use of explicit template arguments

Was it helpful?

Solution

So there's some weird things about explicit specialisation of template members of templated classes. See this question.

One work around is to use a helper class

template< typename T, typename U>
struct FooDispatchHelper
{
   static U dispatch( const Foo<T> * f )
   {
     return f->template bar_internal<U>();
   }
};

template< typename T >
struct FooDispatchHelper<T,T>
{
   static T dispatch( const Foo<T> * f )
   {
     return f->bar_fast();
   }
};

template<typename T>class Foo
{
public:
...
   template<typename U>U bar() const
   {
      return FooDispatchHelper<T,U>::dispatch( this );
   }

  template<typename U> U bar_internal() const;
  T bar_fast() const;

};

A more complete examnple can be found here

OTHER TIPS

One possibility would be to use boost::enable_if / disable_if to choose which version will be available for a particular instantiation:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>

template <class T>
class Foo
{
public:
    template <class U>
    typename boost::disable_if<boost::is_same<T, U>, U>::type bar() const
    { std::cout << "Different U\n"; return U(); }

    template <class U>
    typename boost::enable_if<boost::is_same<T, U>, U>::type bar() const
    { std::cout << "Same U\n"; return U(); }
};


int main()
{
    Foo<int> f;
    f.bar<int>();
    f.bar<float>();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top