Специализировать шаблон с шаблоном
У меня есть (бесплатный) шаблон функции, который выглядит следующим образом
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(); }