Оба будут требовать частичной специализации.Первый будет требовать SFINAE.Поскольку шаблоны функций могут быть только полностью специализированными, вам придется использовать некоторый вспомогательный объект.
template <typename T, int P>
T item(size_t s);
template < typename T, typename Enable = void >
struct item_
{
template < int P >
T apply(size_t s);
};
template < typename T >
struct item_<T, typename enable_if< is_numeric<T> >::type >
{
template < int P >
static T apply(size_t s) { return static_cast<T>(rand()); }
};
template < >
struct item_<std::string, void>
{
template < int P >
static std::string apply(size_t s) { return "NSTHEOSUNTH"; }
};
template < typename T, int P >
T item(size_t s) { return item_<T>::template apply<P>(s); }
В качестве альтернативы вы можете рассмотреть возможность отправки тегов:
struct numeric_tag {};
struct string_tag {};
struct wtf_tag {};
template < typename T, int P >
T item(size_t s, numeric_tag) { return static_cast<T>(rand()); }
template < typename T, int P >
T item(size_t s, string_tag) { return "SNTHEO"; }
template < typename T, int P >
T item(size_t s)
{
item(s, if_
<
is_numeric<T>
, numeric_tag
, typename if_
<
is_same< std::string, T >
, string_tag
, wtf_tag
>::type
>::type());
}
Или вы можете смешатьнекоторые классы мета-функций соответствуют тегам и используют вектор пар ... итерируйте их, проверяя каждый первый (класс мета-функции) и возвращая второй (тег), чтобы выбрать реализацию.
Есть много имного-много способов сделать это.