В документации std::numeric_limits<T>
говорится, что он не должен быть специализированным для не-фундаментальных типов. Как насчет числовых пользовательских типов? Если я определяю свой собственный тип T
, который представляет числовое значение и перегружает числовые операторы и для которого имеет смысл информация, представленная numeric_limits
, - что-нибудь сломается, если я специализирую numeric_limits
для этого типа?
Нормально ли специализировать std:: numeric_limits <T> для пользовательских классов, похожих на число?
Ответ 1
Краткий ответ:
Идем дальше, ничего плохого не произойдет.
Длинный ответ:
Стандарт С++ широко защищает пространство имен ::std
в С++ 11 17.6.4.2.1, но специально разрешает ваше дело в параграфах 1 и 2:
Поведение программы на С++ undefined, если оно добавляет объявления или определения к пространству имен std или к пространство имен в пространстве имен std, если не указано иное. Программа может добавить специализацию шаблона для любого стандартного шаблона библиотеки для пространства имен std, только если объявление зависит от пользовательского типа и специализация соответствует стандартным требованиям библиотеки для исходного шаблона и не является явно запрещено.
[...] Программа может явно создавать шаблон, определенный в стандартной библиотеке, только если декларация зависит от имени определяемого пользователем типа и экземпляра соответствует стандартным требованиям библиотеки для исходного шаблона.
Более старый С++ 03 имеет аналогичное определение в 17.4.3.1/1:
Это undefined для программы на С++ для добавления объявлений или определений в пространство имен std или namespaces в пространстве имен std, если не указано иное. Программа может добавлять специализированные шаблоны для любых стандартный шаблон библиотеки в пространство имен std. Такая специализация (полная или частичная) стандарта шаблон библиотеки приводит к поведению undefined, если декларация не зависит от пользовательского имени внешняя связь и, если специализация не соответствует требованиям стандартной библиотеки для исходного шаблона.
Пройдя этот фундаментальный шаг, вы уже указали, что С++ 03 18.2.1/4 запрещает специализации ::std::numeric_limits
для определенных типов:
Не фундаментальные стандартные типы, такие как комплекс (26.2.2), не должны иметь специализации.
Более современный С++ 11 18.3.2.1/4 имеет несколько другую формулировку:
Неарифметические стандартные типы, такие как
complex<T>
(26.4.2), не должны иметь специализации.
Однако обе эти формулировки допускают специализации для нестандартных типов, которые T
есть, поскольку вы сами определили ее (как уже указывал @BoPersson в комментариях).
Предостережения
С++ 11 18.3.2.3/1 подсказки, которые вы должны (но не требуете), чтобы ваша специализация имела все члены.
Кроме того, вы можете убедиться, что С++ 11 18.3.2.3/2 не нарушена вашей специализацией:
Значение каждого члена специализации numeric_limits для cv-квалифицированного типа cv T должно быть равным к значению соответствующего члена специализации на неквалифицированном типе T.
Что по существу означает, что если вы хотите выделить его для T
, вы также должны сделать это для T const
, T volatile
и T const volatile
.
Ответ 2
Вы не можете специализировать std:: numeric_limits для пользовательского типа. Тип, определенный пользователем, не является арифметическим типом. В стандарте С++ четко написано, что
1 Шаблон класса numeric_limits предоставляет программу на С++ с информация о различных свойствах реализаций представление арифметических типов.
и, например,
4 Неарифметические стандартные типы, такие как complex (26.4.2), должны не имеют специализаций.
Ответ 3
Просто пример:
namespace std {
template<> class numeric_limits<Temperature> {
public:
static Temperature lowest() {return Temperature(-273.15f);};
// One can implement other methods if needed
};
}