Russian Qt Forum

Программирование => Общий => Тема начата: arhiv6 от Февраль 05, 2018, 13:47



Название: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: arhiv6 от Февраль 05, 2018, 13:47
Добрый день. На хабре была статья об Rust (https://habrahabr.ru/post/326896/), точнее об одном его аспекте - как создавать новые типы и сделать автоматические преобразования между ними на примере Цельсий-Фаренгейтов. А есть что-нибудь подобное на С++? Мне нужно будет написать программку, которая работает с физическими величинами, и там хотелось бы физические величины хранить не во float а в своих типах, чтобы как минимум компилятор проверял меня на ошибки вида "прибавил к температуде (в градусах) длинну (в метрах)". + Ту же переменную с температурой мне где-то по коду нужно иметь в цельсиях, где-то в кельвинах, а на выходе пользователь вообще может захотеть увидеть результат в фаренгейтах, т.е. хотелось бы быстро эту переменную преобразовать в разные типы. Думал сделать так:
Код:
typedef float Celsius;
typedef float Fahrenheit;

class Temperature
{
public:
    Fahrenheit toFahrenheit();
    Celsius toCelsius() ;
    bool setTemperature(Celsius temperature);
    bool setTemperature(Fahrenheit temperature);
}
Но оказывается перезагрузка функций и typedef не дружат, можно только оборачивать типы в структуры вот так:
Код:
typedef struct
{
    float temperature;
} Celsius;

typedef struct
{
    float temperature;
} Fahrenheit;
Но это потом неудобно использовать. В С++ по-простому такое не реализовать?
Тут ещё подумалось - а в Python подобное можно сделать? Всё равно хотел на нём попробовать что-нибудь написать.


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: ViTech от Февраль 05, 2018, 14:17
Но это потом неудобно использовать. В С++ по-простому такое не реализовать?

Простота - штука относительная. Зависит от поставленной задачи и уровня владения С++. Создавайте свои классы и в них определяйте все необходимые операции и преобразования.

Примеры библиотек для физических величин: nholthaus/units (https://github.com/nholthaus/units), boost::units (http://www.boost.org/doc/libs/1_66_0/libs/numeric/odeint/doc/html/boost_numeric_odeint/tutorial/using_boost__units.html). Пользоваться ими просто, но их исходный код может быть и непростым :).


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: Igors от Февраль 05, 2018, 15:12
Неплохо сделано напр в классе QColor, он умеет выдавать в разных цветовых моделях. 


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: alex312 от Февраль 05, 2018, 15:24
http://en.cppreference.com/w/cpp/language/user_literal

https://habrahabr.ru/post/140357/


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: Old от Февраль 05, 2018, 15:35
Код
C++ (Qt)
#include <iostream>
 
using namespace std;
 
constexpr double operator "" _cls( long double v )
{
return v;
}
 
constexpr double operator "" _cls( unsigned long long int v )
{
return v;
}
 
constexpr double operator "" _frg( long double v )
{
return (v - 32.) / 1.8;
}
 
constexpr double operator "" _frg( unsigned long long int v )
{
return (v - 32.) / 1.8;
}
 
class Temp
{
public:
using Value = float;
 
Temp() : m_value( 0. ) {}
explicit Temp( Value value ) : m_value( value ) {}
 
inline Value value() const { return m_value; }
 
private:
Value m_value;    // Значение храним в Цельсиях
};
 
int main()
{
Temp t1{ 50.0_cls };
cout << "Temp Celsius = " << t1.value() << endl;
 
Temp t2{ 50.0_frg };
cout << "Temp Celsius = " << t2.value() << endl;
 
 
return 0;
}
 


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: sergek от Февраль 05, 2018, 15:44
Интересно. А что это - operator "" ?


Название: Re: Хочу объявлять свои типы и делать между ними преобразования (как в Rust)
Отправлено: Old от Февраль 05, 2018, 15:53
Интересно. А что это - operator "" ?
https://ru.wikipedia.org/wiki/C%2B%2B11#%D0%9F%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%B8%D0%B5_%D0%BB%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB%D1%8B