Ответ 1
Есть ли причина, почему тип с плавающей запятой не может использоваться в качестве параметра шаблона? В чем причина этого?
Пока я не могу дать окончательную причину, я определенно могу представить, что возникнут проблемы со специализацией шаблона, который принимает значение плавающего указателя в качестве параметра.
Сравнение равенств между числами с плавающей запятой является сложным (в том смысле, что оно иногда дает неожиданные результаты), и при сопоставлении специализаций компилятору необходимо выполнить проверку равенства между предоставленным аргументом и значением, для которого шаблон специализированы.
Другая аналогичная проблема заключается в определении того, являются ли два экземпляра одних и тех же шаблонов тем же типом:
template<double D>
struct X
{
// ...
};
int main()
{
X<3.0> x;
X<some_constant_expression()> y;
}
Являются ли экземпляры x
и y
одного и того же класса? Чтобы решить это, необходимо выполнить проверку равенства между 3.0
и some_constant_expression()
.
Почему это нормально использовать указатель или ссылку на типы с плавающей запятой как параметры без шаблона, но не сырые типы с плавающей запятой?
В отношении вышеприведенного сценария ответ на указатели прост: указатели являются целыми значениями, и сравнение между указателями хорошо определено.
Что касается ссылок, доказательства показывают, что они фактически обрабатываются как указатели:
#include <type_traits>
double a = 0.0;
double b = 0.0;
template<double& D>
struct X : std::false_type { };
template<>
struct X<a> : std::true_type { }
int main()
{
static_assert(X<a>::value, "!"); // Does not fire
static_assert(X<b>::value, "!"); // Fires
}
Кроме того, в параграфе 14.4/1 стандарта С++ 11:
Два идентификатора шаблона относятся к одному и тому же классу или функции, если
- [...]
- их соответствующие аргументы шаблона типа non-type для целочисленного или перечисляемого типа имеют одинаковые значения и
- [...]
- соответствующие им не-тип шаблона-аргументы ссылочного типа относятся к одному и тому же внешнему объекту или функции и
- [...]
[Пример:
template<class E, int size> class buffer { / ... / }; buffer<char,2*512> x; buffer<char,1024> y;
объявляет
x
иy
одинаковым типом, а [...]
Вышеприведенное показывает, что определение того, являются ли два разных экземпляра одного и того же класса шаблонами фактически одним и тем же классом, требует проверки равенства между константными выражениями, используемыми в качестве аргументов шаблона.