Пользовательский литерал для конструктора с двумя аргументами

Пожалуйста, рассмотрите следующий код:

#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 и затем делать некоторые математические операции в теле оператора, чтобы отделить всю часть от десятичной части числа с плавающей запятой ..?

5

Решение

Во-первых, обратите внимание, что имя, которое вы даете для 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, Я просто быстро собрал все вместе, чтобы показать синтаксис, а не учебник по разбору строк.

2

Другие решения

Может быть, перегружая некоторый произвольный оператор:

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);?

1

По вопросам рекламы [email protected]