Пожалуйста, рассмотрите следующий код:
#include <iostream>
class Point
{
public:
int x,y;
Point(int newx, int newy) : x(newx), y(newy) {}
};
Point operator"" x(const unsigned long long i)
{
return Point(i, 0);
}
int main()
{
Point p = 5x;
std::cout << "\npoint is " << p.x << "," << p.y << "\n\n";
return 0;
}
UDL работает, но возможно ли заставить его работать для обоих аргументов конструктора для Point? например 3x5
это буквальный Point(3,5)
или, может быть, даже 3.5x
и затем делать некоторые математические операции в теле оператора, чтобы отделить всю часть от десятичной части числа с плавающей запятой ..?
Во-первых, обратите внимание, что имя, которое вы даете для UDL, должно начинаться с подчеркивания.
Да, это возможно, но может возникнуть вопрос, действительно ли вы этого хотите.
Point operator"" _x(long double x) {
return Point(floor(x), (x-floor(x))*10);
}
int main(){
auto p = 3.5_x;
}
Что касается того, почему вы не хотите. Прямо сейчас, это делает фиксированное умножение на 10, чтобы превратить дробную часть числа с плавающей запятой в целое число. Если вы положите что-то вроде 1.23
, вы, вероятно, ожидали y
быть 23
, но это даст 2.3
вместо.
Хуже того, число, которое вы указали в исходном коде, может легко превратиться в повторяющееся число в двоичном коде, поэтому практически невозможно начать с дробной части числа с плавающей запятой и быть уверенным, что вы производите то, что изначально планировалось.
При использовании числа с плавающей запятой таким способом также не хватает разумного способа обозначить такую точку, как (3, -5)
, Ввод допускает только один знак для всего числа.
Вы можете определить, что вместо этого взять строку, а затем проанализировать строку во время выполнения, чтобы получить правильное значение.
auto p = "3x5"_x;
Большинству людей этот вариант не очень нравится. Необходимость заключать входные данные в кавычки как бы рушит вещи. Если вы все равно хотите это сделать, код будет выглядеть примерно так:
Point operator"" _x(char const * const s, unsigned long long len) {
int x, y;
sscanf(s, "%dx%d", &x, &y);
return Point(x, y);
}
Конечно, вы могли бы предпочесть сделать разбор с чем-то, кроме sscanf
, Я просто быстро собрал все вместе, чтобы показать синтаксис, а не учебник по разбору строк.
Может быть, перегружая некоторый произвольный оператор:
class Point
{
public:
int x,y;
Point(int newx, int newy) : x(newx), y(newy) {}
};
Point operator&(Point p1, Point p2)
{
return Point(p1.x, p2.y);
}
Point operator"" _x(const unsigned long long i)
{
return Point(i, 0);
}
Point operator"" _y(const unsigned long long i)
{
return Point(0, i);
}
Использование:
Point p = 5_x & 42_y;
А если серьезно, я не вижу смысла в этом, это больше печатать по крайней мере. Что не так со старым добрым Point(x,y);
?