Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User-Defined Literal for Two-Argument Constructor

Please consider the following code:

#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;
}

The UDL works, but is it possible to make it work for both arguments of the constructor for Point? e.g. 3x5 is a literal for Point(3,5) or maybe even 3.5x and then doing some math in the operator body to separate the whole part from the decimal part of the float..?

like image 881
1.618 Avatar asked Oct 21 '22 13:10

1.618


1 Answers

First, note that the name you give for a UDL must start with an underscore.

Yes, it's possible, but it may be open to question whether you really want to.

Point operator"" _x(long double x) {
    return Point(floor(x), (x-floor(x))*10);
}

int main(){
    auto p = 3.5_x;
}

As to why you wouldn't want to. Right now, this does a fixed multiplication by 10 to turn the fractional part of the floating point number into an integer. If you put something like 1.23, you probably expected y to be 23, but this will give 2.3 instead.

Worse, the number you gave in the source code may easily turn into a repeating number in binary, so there's almost no way to start from the fractional part of a floating point number and be sure you're producing what was originally intended.

Using a floating point number this way also seems to lack an reasonable way to signify a point like (3, -5). The input only allows one sign for the entire number.

You could define it to take a string instead, and then parse the string at runtime to produce to the correct value.

auto p = "3x5"_x;

Most people don't really like this option much though. Having to enclose the input in quotes kind of ruins things. If you want to do this anyway, the code would look something like this:

Point operator"" _x(char const * const s, unsigned long long len) {
    int x, y;
    sscanf(s, "%dx%d", &x, &y);
    return Point(x, y);
}

Of course, you might prefer to do the parsing with something other than sscanf. I just whipped this together quickly to show the syntax, not as a tutorial in string parsing.

like image 85
Jerry Coffin Avatar answered Oct 23 '22 04:10

Jerry Coffin