2017-01-02 2 views
1

Можно ли преобразовать foo из float в long (и наоборот)?C++ 11 авто. конвертировать из float в long

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

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

Выход всегда:

foo: 1.23457e+12 
foo: 1.23457e+12
+0

Это не проблема, но не используйте 'std :: endl', если вам не нужен дополнительный материал, который он делает. '' \ n'' заканчивает линию. –

ответ

13

Не так, как вы написали. Во-первых,

auto foo = float(1234567891234.1234); 

использует правила дедукции автоматического типа, чтобы определить тип ОРЗ, и результат float. Когда это будет сделано, тип foo будет float, и он установлен в камне (C++ - statically typed, в отличие от, например, Python). Когда вы в следующий раз написать

foo = long(1234567891234.1234); 

тип обув еще float и не волшебно изменилось в long.

Если вы хотите эмулировать «изменение» типа вы можете максимально выполнить бросок:

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

или использовать дополнительную переменную

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

, но быть в курсе возможной потери точности из-за к представлению с плавающей запятой.

Если у вас есть доступ к компилятору C++ 17, вы можете использовать std::variant<long, float>, который представляет собой тип безопасного объединения, для переключения между типами. Если нет, то вы можете просто использовать обычный старый союз как

#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

Или, вы можете использовать технику типа стирания, как

#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

Современная версия указанного выше кода могут быть переписаны на std::shared_ptr, например

#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

std::unique_ptr<void> не будет работать, как только std::shared_ptr реализует тип-стиранием.

Конечно, если вам действительно не нужны размеры хранилища и т. Д., Просто используйте две отдельные переменные.

+0

Итак, что мне делать? – djent

+0

@djent См. Изменение. – vsoftco

+0

Можно ли это сделать: foo = static_cast (foo); и сменили ли foo на длинный тип? Можно ли это сделать каким-то образом? – djent

Смежные вопросы