Специализировать шаблон с шаблоном

У меня есть (бесплатный) шаблон функции, который выглядит следующим образом

template <typename T>
T get();

Теперь я хочу специализировать эту функцию для класса, который сам является шаблоном. Но мой компилятор не хочет его компилировать, и сейчас я спрашиваю, возможно ли это, и как мне этого добиться. Просто для идеи, код может выглядеть следующим образом: (не компилируется)

template <>
template <typename T>
foo_type<T> get<foo_type<T>>()

2 ответа

Решение

То, что вы делаете, называется частичной специализацией шаблона функции. Но частичная специализация шаблона функции не допускается. Перегрузка шаблона функции разрешена, но в этом случае это также невозможно, так как функция имеет только возвращаемый тип, а перегрузка по возвращаемому типу не допускается.

Итак, решение таково:

namespace details
{
     template <typename T>
     struct worker
     {
         static T get();
     };

     template <typename T> //partial specialization of class is allowed
     struct worker<foo<T>>
     {
         static foo<T> get();
     };

}

template <typename T>
T get()
{
  return details::worker<T>::get();
}

Вы также можете использовать перегрузки, если вы определите их для получения одного аргумента, чтобы сделать перегрузку действительной:

namespace details
{
     template <typename T>
     static T get(T*); 

     template <typename T> 
     static foo<T> get(foo<T>*); //now the overload is valid

}

template <typename T>
T get()
{
  return details::get<T>(static_cast<T*>(0));
}

Обратите внимание, что аргумент static_cast<T*>(0) используется, чтобы помочь компилятору выбрать правильную перегрузку. Если T кроме foo<U>тогда будет выбрана первая перегрузка, поскольку тип передаваемого ей аргумента будет T* в отличие от foo<U>*, Если T является foo<U>затем компилятор выберет вторую перегрузку, поскольку он более специализирован и может принять переданный ему аргумент, который foo<U>* в этом случае.

Как сказал Наваз, стандарт просто не позволяет вам этого делать. Однако вы можете извлечь реализацию в статический метод класса и частично специализировать этот класс.

template<class T>
struct get_impl{
  static T get(){ ... }
};

template<class T>
struct get_impl<foo_type<T> >{
  static foo_type<T> get(){ ... }
};

template<class T>
T get(){ return get_impl<T>::get(); }
Другие вопросы по тегам