2012-07-19 19 views
5

Próbuję utworzyć jednostki dla licznika i kilometra. Chcę następnie podsumować i odpowiednio je przekształcić. Wiem, że biblioteka boost :: units ma już system SI, ale chcę stworzyć wszystko od zera, ponieważ wtedy muszę stworzyć własne systemy dla moich projektów (więc robię to, aby się uczyć). Moim celem jest, aby zadeklarować zmienną „długość”, które mogą być modyfikowane za pomocą jednostek, na przykład: Chcę napisaćTworzenie konwersji zdefiniowanych przez użytkownika

Length xLength1 = 5350 * Meters + 2 Kilometers; 

do tego celu, mam stworzył length.h plik zawierający definicje metr i kilometr, a na koniec Oświadczam konwersję pomiędzy tymi dwoma zespołami:

#ifndef LENGTH_H_ 
#define LENGTH_H_ 

#include <boost/units/base_dimension.hpp> 
#include <boost/units/base_unit.hpp> 
#include <boost/units/scaled_base_unit.hpp> 
#include <boost/units/quantity.hpp> 
#include <boost/units/conversion.hpp> 

struct LengthBaseDimension : boost::units::base_dimension<LengthBaseDimension,1>{}; 

typedef LengthBaseDimension::dimension_type LengthDimension; 

struct MeterBaseUnit : boost::units::base_unit<MeterBaseUnit, LengthDimension, 1>{}; 
template <> struct boost::units::base_unit_info<MeterBaseUnit> 
{ 
    static std::string name() { return "meter"; } 
    static std::string symbol() { return "m";  } 
}; 

struct KilometerBaseUnit : boost::units::base_unit<KilometerBaseUnit, LengthDimension, 2>{}; 
template <> struct boost::units::base_unit_info<KilometerBaseUnit> 
{ 
    static std::string name() { return "kilometer"; } 
    static std::string symbol() { return "km";  } 
}; 

// I don't want to use scaled_unit because I need this for my real purpose 
BOOST_UNITS_DEFINE_CONVERSION_FACTOR(KilometerBaseUnit, MeterBaseUnit, double, 1000.0); 

#endif 

Potem utworzyć plik units.h, w którym mogę zdefiniować mój własny system jednostkową

#ifndef LIB_UNITS_H_ 
#define LIB_UNITS_H_ 

#include "length.h" 
#include <boost/units/unit.hpp> 
#include <boost/units/static_constant.hpp> 
#include <boost/units/make_system.hpp> 
#include <boost/units/io.hpp> 

typedef boost::units::make_system<MeterBaseUnit>::type UnitsSystem; 

typedef boost::units::unit<boost::units::dimensionless_type, UnitsSystem> Dimensionless; 
typedef boost::units::unit<LengthDimension     , UnitsSystem> SystemLength; 


BOOST_UNITS_STATIC_CONSTANT(Kilometer , SystemLength); 
BOOST_UNITS_STATIC_CONSTANT(Kilometers , SystemLength); 
BOOST_UNITS_STATIC_CONSTANT(Meter  , SystemLength); 
BOOST_UNITS_STATIC_CONSTANT(Meters  , SystemLength); 

// Typedefs of dimensions 
typedef boost::units::quantity<SystemLength> Length; 

#endif 

Przynajmniej mogę używać tego nagłówka w moim głównej funkcji

#include "units.h" 
#include <iostream> 

int main(void) 
{ 
    Length xLength1 (300.0 * Meters); 
    Length xLength2 (1500.0 * Kilometer); 
    Length xLength3; 
    std::cout << xLength2 << std::endl; 
    xLength3 = xLength1 + xLength2; 

    return 0; 
} 

Te projekty kompiluje, ale to nie to, co chcę. Kiedy drukuję zmienną x długość 2, otrzymuję 1500 m zamiast 1500 km lub 1500000 m. Suma też jest błędna, ponieważ obijam 1800 m. To tak, jakbym uważał kilometry za metry, a konwersja nie działa.

Co robię źle?

+0

Definiujesz "Kilometr" tak, jak "Meter". Nie pamiętam z góry, jaki jest preferowany sposób definiowania "Kilometru" (być może istnieje inne makro), ale możesz spróbować czegoś takiego jak 'const Length Kilometry = 1000 * Meters;' (tasowanie kolejności definicji). –

+1

Ale w tym przypadku nie mogę pisać i przyjmować wartości w kilometrach, ale tylko w metrach. Chcę mieć możliwość pracy z obydwoma jednostkami i używać obu wartości w razie potrzeby. – Jepessen

+0

Po prostu w heads-upie, jeśli używasz MSVC++ lub gcc, możesz zastąpić strażnik '#DEFDEF LENGTH_H_' itd.' #pragma once' na górze każdego nagłówka. –

Odpowiedz

0

Chyba że jesteś projektem replikowania biblioteki Boost, wydaje się to szalony sposób kodowania systemu jednostek. Template hackery rzadko jest najlepszą opcją.

Zamiast tego użyj klasy! Nie rzeczywisty kod poniżej:

class temperature{ 
    double temp; //always in kelvin 
    temperature(double temperature, char unit){ 
     if(unit=='k') 
       temp=temperature 
     if(unit=='c') 
       temp=temperature+273 
    } 
}; 

I tak do realizacji konwersji z powrotem do dowolnej jednostki. Zasadniczo wybierasz jednostkę podstawową, w której wszystko jest przechowywane i konwertujesz do iz niej. Jeśli robisz SI, być może gram, metry, sekundy, Kelwin, itd.

+0

To nie jest metoda Boost.Units, więc nie odpowiada na pytanie. – Ruslan

Powiązane problemy