То, что вы делаете, называется частичная специализация шаблона функции.Но частичная специализация шаблона функции не допускается.Перегрузка шаблона функции разрешена, но в этом случае это также невозможно, поскольку функция имеет только тип возвращаемого значения, а перегрузка по типу возвращаемого значения не допускается.
Таким образом, решение таково:
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>
, то компилятор выберет вторую перегрузку, поскольку она more специализирована и может принять переданный ей аргумент, который в данном случае равен foo<U>*
.