C ++ оптимизирует функцию шаблона класса, когда параметры шаблона идентичны - PullRequest
2 голосов
/ 28 января 2010

У меня есть шаблонный класс с методом шаблона внутри, который дает два шаблонных параметра T и U. Операция довольно дорогая и обнаруживается в профилировании как основное использование процессорного времени. Я мог бы несколько оптимизировать его, но только для случая, когда T == U (что довольно распространено), однако я не уверен в синтаксисе для этого ...

Рассматриваемый класс и метод выглядят так:

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

Foo :: bar обычно вызывается из некоторого другого кода шаблона, поэтому, даже если я создал отдельный метод (например, "T fastBar () const"), я не знаю, как id будет вызывать другой код шаблона, который версия, где это возможно ...

Я пытался создать явную специализацию для T == U, но VC9 дал мне ошибки

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

ошибка C2768: 'Foo :: bar': недопустимое использование явных аргументов шаблона

Ответы [ 2 ]

4 голосов
/ 28 января 2010

Итак, есть некоторые странные вещи в явной специализации членов шаблонов шаблонных классов. Смотрите этот вопрос .

Обходной путь - использовать вспомогательный класс

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;

};

Более полный пример можно найти здесь

2 голосов
/ 28 января 2010

Можно использовать boost::enable_if / disable_if, чтобы выбрать, какая версия будет доступна для конкретного экземпляра:

#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>();
}
...