Click here to Skip to main content
15,889,116 members
Articles / Programming Languages / C++11

Application of C++11 User-Defined Literals to Handling Scientific Quantities, Number Representation and String Manipulation

Rate me:
Please Sign up or sign in to vote.
4.98/5 (30 votes)
31 Aug 2012CPOL7 min read 52.1K   379   41  
keywords: user-defined literals , templates, constant expressions, recursive functions
// scientific_units2.cpp : Defines the entry point for the console application.
// with user-defined literals

#include<iostream>
#include<string>
#include <sstream>
#include <iomanip>


using namespace std;

//internally for everything use SI units.
//mass in kilograms,
//time in seconds
//length in meters

template<int M, int L, int T>
class Quantity
{
public:
    constexpr Quantity(double val) : value(val){}

    constexpr Quantity& operator+=(const Quantity& rhs)
    {
                    value+=rhs.value;
                    return *this;
    }

    constexpr Quantity& operator-=(const Quantity& rhs)
    {
                    value-=rhs.value;
                    return *this;
    }

    constexpr double Convert(const Quantity& rhs)
    {
                    return value/rhs.value;                    
    }

    constexpr double getValue() const
    {
                    return value;
    }        

private:    
    double value;    
};

template <int M, int L, int T>
constexpr Quantity<M,L,T> operator+(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return Quantity<M,L,T>(lhs)+=rhs;
}
template <int M, int L, int T>
constexpr Quantity<M,L,T> operator-(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return Quantity<M,L,T>(lhs)-=rhs;
}
template <int M1, int L1, int T1, int M2, int L2, int T2>
constexpr Quantity<M1+M2,L1+L2,T1+T2> operator*(const Quantity<M1,L1,T1>& lhs, const Quantity<M2,L2,T2>& rhs)
{
               return Quantity<M1+M2,L1+L2,T1+T2>(lhs.getValue()*rhs.getValue());
}
template <int M, int L, int T>
constexpr Quantity<M,L,T> operator*(const double& lhs, const Quantity<M,L,T>& rhs)
{
               return Quantity<M,L,T>(lhs*rhs.getValue());
}

template <int M1, int L1, int T1, int M2, int L2, int T2>
constexpr Quantity<M1-M2,L1-L2,T1-T2> operator/(const Quantity<M1,L1,T1>& lhs, const Quantity<M2,L2,T2>& rhs)
{
               return Quantity<M1-M2,L1-L2,T1-T2>(lhs.getValue()/rhs.getValue());
}

template <int M, int L, int T>
constexpr Quantity<-M, -L, -T> operator/(double x, const Quantity<M,L,T>& rhs)
{
               return Quantity<-M,-L,-T>(x/rhs.getValue());
}

template <int M, int L, int T>
constexpr Quantity<M, L, T> operator/(const Quantity<M,L,T>& rhs, double x)
{
               return Quantity<M,L,T>(rhs.getValue()/x);
}

template <int M, int L, int T>
constexpr bool operator==(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return (lhs.getValue()==rhs.getValue());
}

template <int M, int L, int T>
constexpr bool operator!=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return (lhs.getValue()!=rhs.getValue());
}

template <int M, int L, int T>
constexpr bool operator<=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return lhs.getValue()<=rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator>=(const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return lhs.getValue()>=rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator< (const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return lhs.getValue()<rhs.getValue();
}
template <int M, int L, int T>
constexpr bool operator> (const Quantity<M,L,T>& lhs, const Quantity<M,L,T>& rhs)
{
               return lhs.getValue()>rhs.getValue();
}

typedef Quantity<1,0,0> Mass;
typedef Quantity<0,1,0> Length;
typedef Quantity<0,2,0> Area;
typedef Quantity<0,3,0> Volume;
typedef Quantity<0,0,1> Time;
typedef Quantity<0,1,-1> Speed;
typedef Quantity<0,1,-2> Acceleration;
typedef Quantity<0,0,-1> Frequency;
typedef Quantity<1,1,-2> Force;
typedef Quantity<1,-1,-2> Pressure;

//length units - verify the constants
constexpr Length metre(1.0);
constexpr Length decimetre = metre/10;
constexpr Length centimetre = metre/100;
constexpr Length millimetre = metre/1000;
constexpr Length kilometre = 1000 * metre;
constexpr Length inch = 2.54 * centimetre;
constexpr Length foot = 12 * inch;
constexpr Length yard = 3 * foot;
constexpr Length mile = 5280 * foot;
constexpr Frequency Hz(1.0);


constexpr Area kilometre2 = kilometre*kilometre;
constexpr Area metre2 = metre*metre;
constexpr Area decimetre2 = decimetre*decimetre;
constexpr Area centimetre2 = centimetre*centimetre;
constexpr Area millimetre2 = millimetre * millimetre;
constexpr Area inch2 =inch*inch;
constexpr Area foot2 = foot*foot;
constexpr Area mile2 = mile*mile;

constexpr Volume kilometre3 = kilometre2*kilometre;
constexpr Volume metre3 = metre2*metre;
constexpr Volume decimetre3 = decimetre2*decimetre;
constexpr Volume litre = decimetre3;
constexpr Volume centimetre3 = centimetre2*centimetre;
constexpr Volume millimetre3 = millimetre2 * millimetre;
constexpr Volume inch3 =inch2*inch;
constexpr Volume foot3 = foot2*foot;
constexpr Volume mile3 = mile2*mile;




//time units
constexpr Time second(1.0);
constexpr Quantity<0,0,2> second2(1.0);
constexpr Time minute = 60 * second;
constexpr Time hour = 60 * minute;
constexpr Time day = 24 * hour;

//mass units
constexpr Mass kg(1.0);
constexpr Mass gramme = 0.001 * kg;
constexpr Mass tonne = 1000 * kg;
constexpr Mass ounce = 0.028349523125 * kg; 
constexpr Mass pound = 16 * ounce;
constexpr Mass stone = 14 * pound;

constexpr Length operator"" _mm(long double x) { return x*millimetre; }
constexpr Length operator"" _cm(long double x)  { return x*centimetre; }
constexpr Length operator"" _m(long double x)  { return x*metre; }
constexpr Length operator"" _km(long double x) { return x*kilometre; }
constexpr Length operator"" _mi(long double x) { return x*mile; }
constexpr Length operator"" _yd(long double x) { return x*yard; }
constexpr Length operator"" _ft(long double x) { return x*foot; }
constexpr Length operator"" _in(long double x) { return x*inch; }

constexpr Speed operator"" _mps(long double x)  { return Speed(x); };
constexpr Speed operator"" _miph(long double x) { return x*mile/hour; };
constexpr Speed operator"" _kmph(long double x) { return x*kilometre/hour; };

constexpr Frequency operator"" _Hz(long double x)  { return Frequency(x); };
constexpr Time operator"" _s(long double x)  { return Time(x); };
constexpr Time operator"" _min(long double x)  { return x*minute; };
constexpr Time operator"" _h(long double x)  { return x*hour; };
constexpr Time operator"" _day(long double x)  { return x*day; };

constexpr Mass operator"" _kg(long double x)  { return Mass(x); };
constexpr Mass operator"" _g(long double x)  { return x*gramme; };
constexpr Mass operator"" _t(long double x)  { return x*tonne; };
constexpr Mass operator"" _oz(long double x)  { return x*ounce; };
constexpr Mass operator"" _lb(long double x)  { return x*pound; };
constexpr Mass operator"" _st(long double x)  { return x*stone; };

constexpr Acceleration operator"" _mps2(long double x)  { return Acceleration(x); };


#define ConvertTo(_x, _y) (_x).Convert(1.0_##_y)

constexpr long double operator "" _pi(long double x) { return x * 3.1415926535897932384626433832795;}
constexpr long double operator "" _pi(unsigned long long int x) { return x * 3.1415926535897932384626433832795;}

constexpr long double operator "" _sq(long double x) { return x * x;}
constexpr unsigned long long int operator "" _sq(unsigned long long x) { return x * x;}


constexpr unsigned long long ToBinary(unsigned long long x, const char* s)
{
    return (!*s ? x : ToBinary(x + x + (*s =='1'? 1 : 0), s+1));
}


constexpr unsigned long long int operator "" _b(const char* s) { return ToBinary(0,s);}



int main()
{
               
    Length length = 100000.0_cm;
    //Length LengthinFeet = LengthinCMs*convert(centimetre, foot);
    std::cout << std::setprecision(15) << " 100000*centimetre = " << ConvertTo(length,ft) << " feet" << std::endl;                             


               
    //get in terms of miles and feet
    double total_in_miles = ConvertTo(length,mi);
    double total_in_feet =  ConvertTo(length,ft);

    cout << total_in_miles << " miles" << endl;               
    cout << total_in_feet << " feet" << endl;

    std::cout << " 1 foot = " << ConvertTo(1.0_ft,cm) << " cm" << std::endl;                             

    Length Length100 = 100.0_km;
    Time time = 2.0_h;

    Speed sp1 = Length100 / time; // metre/second               

    cout << "100 km in 2 hours: " << ConvertTo(sp1,kmph) << " km/hour" << endl;               
    cout << "100 km in 2 hours: " << ConvertTo(sp1,miph) << " mile/hour" << endl;               

    Frequency fr1 = 100.0_Hz;
    Time interval = 1.0/fr1;

    cout << "frequency (1/s): " << ConvertTo(fr1,Hz) << endl;
    cout << "interval (s): " << ConvertTo(interval,s) << endl;

    Acceleration a1 = 9.8_mps2;

    cout << "accelaration (m/s2): " << ConvertTo(a1,mps2) << endl;


    cout << "1 mile: " << ConvertTo(1.0_mi, m) << " metres" << endl;


    cout << "my mass: " << ConvertTo(80.0_kg,kg) << " kg" << endl;

    cout << "my mass: " << ConvertTo(80.0_kg,st) << " stone" << endl;

    cout << "my mass: " << ConvertTo(80.0_kg,lb) << " pounds" << endl;



    cout << "one pound in grammes: " <<  ConvertTo(1.0_lb, g) << endl;

    cout << "one pound in kg: " << ConvertTo(1.0_lb,kg) << endl;

    cout << "one pound in ounces: " << ConvertTo(1.0_lb,oz) << endl;

    std::cout << "20 miles = "  << ConvertTo(20.0_mi,m) << " metres" << std::endl;
    std::cout << "20 miles = " << ConvertTo(20.0_mi,km) << " kilometres" << std::endl;
    std::cout << "20 miles = " << ConvertTo(20.0_mi,yd) << " yards" << std::endl;
    std::cout << "100 inches = "  << ConvertTo(100.0_in,mi)  << " miles" << std::endl;    
    std::cout << "299792458 metres per second = " << ConvertTo(299792458.0_mps,kmph)  << " km/h" << std::endl;     
    std::cout << "299792458 metres per second = "  << ConvertTo(299792458.0_mps,miph)  << " miles/h" << std::endl;
    std::cout << "3.5 hours  * 3 miles/hour  =  " << ConvertTo(3.5_h * 3.0_miph, mi) << " miles" << std::endl;
    std::cout << "(3.5 metres/s) / (2 sec) = " << ConvertTo(3.5_mps/2.0_s, mps2)  << " m/s2" << std::endl;

    std::cout << "2.0 pi = " << 2.0_pi  << std::endl;
    std::cout << "2 pi = " << 2_pi  << std::endl;
    std::cout << "-2.0 pi = " << -2_pi  << std::endl;
    std::cout << "-2.5 pi = " << -2.5_pi  << std::endl;    
    std::cout << " 4^2 = " << 4_sq  << std::endl;
    std::cout << " 2.5^2 = " << 2.5_sq  << std::endl;
    std::cout << " 29^2 = " << 29_sq  << std::endl;
    std::cout << "1101(2) = " << 1101_b  << std::endl;
    std::cout << "1111 1111 1111 1111 1111(2) = " << std::hex << 11111111111111111111_b << "(16)" << std::endl;
    std::cout << "10 1010 1010 1010 1010(2) = " << std::hex << 101010101010101010_b  << "(16)" << std::endl;

    return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions