Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 auto. convert from float to long

Is it possible to convert foo from float to long (and vice versa)?

auto foo = float(1234567891234.1234);
cout << "foo: " << foo << endl;

foo = long(1234567891234.1234);
cout << "foo: " << foo << endl;

The output is always:

foo: 1.23457e+12
foo: 1.23457e+12
like image 543
djent Avatar asked Apr 28 '26 12:04

djent


1 Answers

Not in the way you wrote it. First,

auto foo = float(1234567891234.1234);

uses auto type deduction rules to infer the type of the RHS, and the result is float. Once this is done, the type of foo is float and it is set in stone (C++ is statically typed, unlike e.g. Python). When you next write

foo = long(1234567891234.1234);

the type of foo is still float and it is not magically changed to long.

If you want to emulate a "change" of type you can at most perform a cast:

 cout << "foo (as long): " << static_cast<long>(foo) << endl;

or use an additional variable

long foo_long = foo; // again you may have a loss of precision 

but be aware of possible precision loss due to floating point representation.

If you have access to a C++17 compiler, you can use an std::variant<long, float>, which is a type-safe union, to switch between types. If not, you can just use a plain old union like

#include <iostream>

union Foo
{
    float f;
    long l;
};

int main()
{
    Foo foo;
    foo.f = float(1234567891234.1234); // we set up the float member
    std::cout << "foo: " << foo.f << std::endl;

    foo.l = long(1234567891234.1234); // we set up the long member
    std::cout << "foo: " << foo.l << std::endl;
}

Live on Coliru

Or, you can use a type-erasure technique like

#include <iostream>

int main()
{
    void *foo; // we will store the object via this pointer

    foo = new int{42};
    std::cout << *(int*)foo << '\n';
    operator delete(foo); // don't do delete foo, it is undefined behaviour

    foo = new float{42.42};
    std::cout << *(float*)foo << '\n';
    operator delete(foo); // don't do delete foo, it is undefined behaviour
}

Live on Coliru

The modern version of the code above can be re-written with a std::shared_ptr like

#include <iostream>
#include <memory>

int main()
{
    std::shared_ptr<void> foo{new int{42}};
    std::cout << *(int*)foo.get() << '\n';

    foo.reset(new float{42.42});
    std::cout << *(float*)foo.get() << '\n';
}

Live on Coliru

A std::unique_ptr<void> won't work as only std::shared_ptr implements type-erasure.

Of course, if you don't really care about storage size etc, just use 2 separate variables.

like image 118
vsoftco Avatar answered Apr 30 '26 02:04

vsoftco



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!