Question

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..?

Was it helpful?

Solution

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.

OTHER TIPS

Maybe by overloading some arbitrary operator:

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

Usage:

Point p = 5_x & 42_y;

But seriously, I see no point in doing this, it's more typing at the very least. What's wrong with good old Point(x,y);?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top