C++ optimise class template function when template parameters identical
-
23-09-2019 - |
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
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>();
}