Как специализировать этот шаблон (обращая внимание на тип возврата) - PullRequest
0 голосов
/ 12 января 2011

Я бы хотел специализировать следующий шаблон:

template <typename T, int P>
T item(size_t s);

на что-то подобное:

template<int P>
T item<typename T>(size_t s)
{
//for all numeric types
    return static_cast<T>(rand());
}

template <int P>
string item<string>(size_t s)
{
    return "asdf";
}

Ответы [ 3 ]

5 голосов
/ 12 января 2011

Вы не можете частично специализировать такие шаблоны функций. Частичная специализация шаблонов только для шаблонов классов.

Однако вы можете использовать boost::enable_if, чтобы «эмулировать» тот тип частичной специализации шаблона функции, который вы ищете.

// Specialization for std::string
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, std::string> >::type* = 0)
{
   ....
}

// Specialization for int
//
template <int P, typename T>
T item(size_t, typename boost::enable_if<boost::is_same<T, int> >::type* = 0)
{
    ....
}

Таким образом, если вы вызовете item<5, std::string>(10), вы вызовете первую функцию, а если вы вызовете item<5, int>(10), вы вызовете вторую функцию.

В качестве альтернативы, если вы по какой-то причине не хотите использовать Boost, другой способ - создать шаблон класса диспетчера, который, конечно, может быть частично специализированным.

1 голос
/ 12 января 2011

Оба будут требовать частичной специализации.Первый будет требовать 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());
}

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

Есть много имного-много способов сделать это.

0 голосов
/ 12 января 2011

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

Правильное связывание частичных специализаций шаблонов функций, если бы они существовали, было бы задано чем-то вроде:

template<class T, class U> X f(T,U);

specialise template<class A, class B> X f(A,B) 
  with template <class K> <K,K*>;

Классы шаблонов имеютболее простая специализация специализации, потому что они однозначно идентифицируются по имени, перегрузке функций, так что этого недостаточно.

...