简体   繁体   中英

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM