Нормально ли специализировать std:: numeric_limits <T> для пользовательских классов, похожих на число? - программирование
Подтвердить что ты не робот

Нормально ли специализировать std:: numeric_limits <T> для пользовательских классов, похожих на число?

В документации std::numeric_limits<T> говорится, что он не должен быть специализированным для не-фундаментальных типов. Как насчет числовых пользовательских типов? Если я определяю свой собственный тип T, который представляет числовое значение и перегружает числовые операторы и для которого имеет смысл информация, представленная numeric_limits, - что-нибудь сломается, если я специализирую numeric_limits для этого типа?

4b9b3361

Ответ 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
    };
}