Как правильно объявить специализацию шаблона для другого типа шаблона? - PullRequest
3 голосов
/ 28 апреля 2010

Обычное определение для специализации шаблонной функции примерно так:

class Foo {
    [...]
};

namespace std {
    template<>
    void swap(Foo& left, Foo& right) {
        [...]
    }
} // namespace std

Но как правильно определить специализацию, когда тип, для которого она специализируется, сам является шаблоном? Вот что у меня есть:

template <size_t Bits>
class fixed {
    [...]
};

namespace std {
    template<size_t Bits>
    void swap(fixed<Bits>& left, fixed<Bits>& right) {
        [...]
    }
} // namespace std

Это правильный способ объявить swap? Предполагается, что это специализация шаблонной функции std::swap, но я не могу сказать, видит ли ее компилятор как таковой или считает, что это перегрузка или что-то в этом роде.

Ответы [ 4 ]

4 голосов
/ 28 апреля 2010

Ваше решение - это не специализация шаблонов, а перегрузка функции в пространстве имен std, что соответствует "неопределенному поведению" в соответствии со стандартом c ++.

Этот вопрос точно ваш вопрос.

Скотт Мейерс обсуждает это в Effective C ++, и на usenet's comp.lang.c ++ .

имеется цепочка последующих действий.
  • Он предлагает вам определить это в собственном пространстве имен фиксированного.
  • Убедитесь, что 'fixed' находится в пространстве имен.
  • Не добавляйте префиксы к вызовам с помощью 'std ::'.
  • Пусть Поиск по Кенигу (зависит от аргумента) найдет правильную функцию подкачки.

Если вы видите ошибки компиляции при попытке определить это в пространстве имен std, это, вероятно, связано с неудачным выбором имен классов :) Когда в namespace std «fixed» рассматривается как std::fixed, с плавающей точкой Оператор точности.

3 голосов
/ 28 апреля 2010

Частичная специализация шаблонов функций не допускается, поэтому шаблон для fixed<Bits> объявляет новую перегрузку, а не специализацию.

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

2 голосов
/ 28 апреля 2010

Синтаксически ваша «специализация» выполнена правильно. Однако, как уже отмечалось, это не частичная специализация, а перегрузка функции. Шаблоны функций не поддерживают частичную специализацию.

Стоит отметить, что добавление чего-либо в пространство имен std запрещено спецификацией языка (см. 17.4.3.1/1). Я понимаю, почему вы настаивали на том, чтобы делать это именно в std, поскольку пытались частично специализировать std::swap. Поскольку ваш swap на самом деле является перегрузкой, а не специализацией, вы можете безопасно сделать это вне std, в том же пространстве имен, которое содержит yor fixed. Зависящий от аргумента поиск имени («поиск по Кенигу») должен убедиться, что ваш swap найден поиском имени при применении к аргументам типа fixed (если вызывающий код явно не ссылается на std::swap вместо просто swap ).

0 голосов
/ 28 апреля 2010

Параметр шаблона не может быть объявлен со значением, которое не определено до времени выполнения. Чтобы использовать числа для параметра шаблона, он должен быть «const», поэтому его можно разрешить во время компиляции:

template <const size_t Bits> 
class fixed { 
    [...] 
}; 

namespace std { 
    template<const size_t Bits> 
    void swap(fixed<Bits>& left, fixed<Bits>& right) { 
        [...] 
    } 
} // namespace std 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...