Mirror reflection library - Puddle compile-time layer 0.5.13

puddle/example/weather.cpp

This example shows the usage of the Puddle compile-time layer.

Copyright 2008-2011 Matus Chochlik. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <mirror/mirror.hpp>
#include <mirror/utils/quick_reg.hpp>
#include <puddle/puddle.hpp>

#include <type_traits>
#include <iostream>

enum class month_name {
    january, february, march, april, may, june,
    july, august, september, october, november, december
};

namespace weather {

enum class type
{
    sunny, clear, mostly_sunny, partly_sunny, partly_cloudy, mostly_cloudy,
    cloudy, overcast, storm, thunderstorm, snowstorm, mist, fog,
    light_rain, rain, showers, snow_showers, snow, hail
};

enum class temperature_unit
{
    degrees_celsius, degrees_fahrenheit
};

enum class speed_unit
{
    meters_per_second, kilometers_per_second, miles_per_hour,
    knots
};

enum class cardinal_direction
{
    N, S, E, W, NE, NW, SE, SW, NNE, ENE, NNW, WNW, SSE, ESE, SSW, WSW
};

struct temperature
{
    double value;
    temperature_unit units;
};

struct wind_info
{
    double avg_speed;
    double max_speed;
    speed_unit units;
    cardinal_direction direction;
    bool high_wind_warning;
};

struct status
{
    type conditions;
    temperature min_temperature, max_temperature;
    double humidity;
    wind_info wind;
};

struct forecast
{
    int year;
    month_name month;
    int day;
    std::string place;
    status morning, afternoon, evening, night;
};

forecast today = {
    2011, month_name::april, 10,
    "Tatry",
    {
        type::mostly_cloudy,
        {3.0, temperature_unit::degrees_celsius},
        {7.0, temperature_unit::degrees_celsius},
        41.0,
        {25.0, 40.0, speed_unit::meters_per_second, cardinal_direction::N, true}
    },
    {
        type::overcast,
        {4.0, temperature_unit::degrees_celsius},
        {9.0, temperature_unit::degrees_celsius},
        44.0,
        {20.0, 35.0, speed_unit::meters_per_second, cardinal_direction::N, true}
    },
    {
        type::rain,
        {7.0, temperature_unit::degrees_celsius},
        {13.0, temperature_unit::degrees_celsius},
        47.0,
        {15.0, 30.0, speed_unit::meters_per_second, cardinal_direction::NNW, true}
    },
    {
        type::snow,
        {0.0, temperature_unit::degrees_celsius},
        {4.0, temperature_unit::degrees_celsius},
        52.0,
        {5.0, 10.0, speed_unit::meters_per_second, cardinal_direction::NW, false}
    }
};

forecast tomorrow = {
    2011, month_name::april, 11,
    "Tatry",
    {
        type::snow_showers,
        {-1.0, temperature_unit::degrees_celsius},
        {2.0, temperature_unit::degrees_celsius},
        50.0,
        {5.0, 10.0, speed_unit::meters_per_second, cardinal_direction::NW, false}
    },
    {
        type::showers,
        {3.0, temperature_unit::degrees_celsius},
        {7.0, temperature_unit::degrees_celsius},
        50.0,
        {2.0, 5.0, speed_unit::meters_per_second, cardinal_direction::WNW, false}
    },
    {
        type::mostly_cloudy,
        {7.0, temperature_unit::degrees_celsius},
        {12.0, temperature_unit::degrees_celsius},
        47.0,
        {3.0, 7.0, speed_unit::meters_per_second, cardinal_direction::W, false}
    },
    {
        type::partly_cloudy,
        {2.0, temperature_unit::degrees_celsius},
        {5.0, temperature_unit::degrees_celsius},
        40.0,
        {5.0, 10.0, speed_unit::meters_per_second, cardinal_direction::W, false}
    }
};


} // namespace weather

MIRROR_REG_BEGIN

MIRROR_QREG_GLOBAL_SCOPE_ENUM(month_name,
    (january)(february)(march)(april)(may)(june)
    (july)(august)(september)(october)(november)(december)
)

MIRROR_QREG_GLOBAL_SCOPE_NAMESPACE(weather)

MIRROR_QREG_ENUM(weather, type,
    (sunny)(clear)(mostly_sunny)(partly_sunny)(partly_cloudy)(mostly_cloudy)
    (cloudy)(overcast)(storm)(thunderstorm)(snowstorm)(mist)(fog)
    (light_rain)(rain)(showers)(snow_showers)(snow)(hail)
)

MIRROR_QREG_ENUM(weather, temperature_unit,
    (degrees_celsius)(degrees_fahrenheit)
)

MIRROR_QREG_ENUM(weather, speed_unit,
    (meters_per_second)(kilometers_per_second)(miles_per_hour)
    (knots)
)

MIRROR_QREG_ENUM(weather, cardinal_direction,
    (N)(S)(E)(W)(NE)(NW)(SE)(SW)(NNE)(ENE)(NNW)(WNW)(SSE)(ESE)(SSW)(WSW)
)

MIRROR_QREG_POD_CLASS(
    struct, weather, temperature,
    (value)(units)
)

MIRROR_QREG_POD_CLASS(
    struct, weather, wind_info,
    (avg_speed)
    (max_speed)
    (units)
    (direction)
    (high_wind_warning)
)

MIRROR_QREG_POD_CLASS(
    struct, weather, status,
    (conditions)
    (min_temperature)
    (max_temperature)
    (humidity)
    (wind)
)

MIRROR_QREG_POD_CLASS(
    struct, weather, forecast,
    (year)(month)(day)
    (place)
    (morning)(afternoon)(evening)(night)
)

MIRROR_QREG_FREE_VARIABLES(weather, (today)(tomorrow))

MIRROR_REG_END

class json_printer
{
private:
    int indent_level;

    std::ostream& indented(std::ostream& out) const
    {
        for(int i=0;i!=indent_level;++i) out << "  ";
        return out;
    }


    template <typename T>
    static std::true_type is_writable(
        T*,
        decltype(std::cout << (*((T*)nullptr)) == std::cout) = false
    );
    static std::false_type is_writable(...);

    // checks if T is directly writable to std::cout
    template <typename T>
    static auto writable(const T&) -> decltype(is_writable((T*)nullptr));

    // prints types directly writable to ostream
    template <typename MetaObject>
    void do_print(
        MetaObject mo,
        mirror::meta_type_tag,
        std::true_type
    ) const
    {
        std::cout << "'" << mo.get() << "'";
    }

    // prints enumerated type values
    template <typename MetaObject>
    void do_print(
        MetaObject mo,
        mirror::meta_enum_tag,
        std::false_type
    ) const
    {
        std::cout << "'" << mo.value_name() << "'";
    }

    // prints elaborated type values which are not directly writable to cout
    template <typename MetaObject>
    void do_print(
        MetaObject mo,
        mirror::meta_class_tag,
        std::false_type
    ) const
    {
        if(mo.attributes().empty()) std::cout << "N/A";
        else
        {
            std::cout << "{" << std::endl;
            mo.attributes().for_each(json_printer(indent_level+1));
            indented(std::cout) << "}";
        }
    }

    // prints a variable
    template <typename MetaVariable>
    void print(MetaVariable mv, mirror::meta_variable_tag) const
    {
        indented(std::cout) << "'" << mv.base_name() << "': ";
        std::false_type wr;
        auto cat = mv.type().category();
        do_print(puddle::instance_of(mv), cat, wr);
    }

    // prints an instance
    template <typename MetaInstance>
    void print(MetaInstance mi, puddle::meta_instance_tag) const
    {
        indented(std::cout)<< "'" << mi.variable().base_name() << "': ";
        decltype(writable(mi.get())) wr;
        auto cat = mi.variable().type().category();
        do_print(mi, cat, wr);
    }
public:
    json_printer(int indent = 0)
     : indent_level(indent)
    { }

    template <typename MetaObject>
    void operator()(MetaObject mo, bool first, bool last) const
    {
        print(mo, mo.category());
        if(!last) std::cout << ",";
        std::cout << std::endl;
    }
};


int main(void)
{
    auto meta_weather = puddle::adapt<MIRRORED_NAMESPACE(weather)>();
    meta_weather.free_variables().for_each(json_printer());
    std::cout << std::endl;
    return 0;
}

/* Example of output:
 | 'today': {
 |   'year': '2011',
 |   'month': 'april',
 |   'day': '10',
 |   'place': 'Tatry',
 |   'morning': {
 |     'conditions': 'mostly_cloudy',
 |     'min_temperature': {
 |       'value': '3',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '7',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '41',
 |     'wind': {
 |       'avg_speed': '25',
 |       'max_speed': '40',
 |       'units': 'meters_per_second',
 |       'direction': 'N',
 |       'high_wind_warning': '1'
 |     }
 |   },
 |   'afternoon': {
 |     'conditions': 'overcast',
 |     'min_temperature': {
 |       'value': '4',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '9',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '44',
 |     'wind': {
 |       'avg_speed': '20',
 |       'max_speed': '35',
 |       'units': 'meters_per_second',
 |       'direction': 'N',
 |       'high_wind_warning': '1'
 |     }
 |   },
 |   'evening': {
 |     'conditions': 'rain',
 |     'min_temperature': {
 |       'value': '7',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '13',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '47',
 |     'wind': {
 |       'avg_speed': '15',
 |       'max_speed': '30',
 |       'units': 'meters_per_second',
 |       'direction': 'NNW',
 |       'high_wind_warning': '1'
 |     }
 |   },
 |   'night': {
 |     'conditions': 'snow',
 |     'min_temperature': {
 |       'value': '0',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '4',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '52',
 |     'wind': {
 |       'avg_speed': '5',
 |       'max_speed': '10',
 |       'units': 'meters_per_second',
 |       'direction': 'NW',
 |       'high_wind_warning': '0'
 |     }
 |   }
 | },
 | 'tomorrow': {
 |   'year': '2011',
 |   'month': 'april',
 |   'day': '11',
 |   'place': 'Tatry',
 |   'morning': {
 |     'conditions': 'snow_showers',
 |     'min_temperature': {
 |       'value': '-1',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '2',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '50',
 |     'wind': {
 |       'avg_speed': '5',
 |       'max_speed': '10',
 |       'units': 'meters_per_second',
 |       'direction': 'NW',
 |       'high_wind_warning': '0'
 |     }
 |   },
 |   'afternoon': {
 |     'conditions': 'showers',
 |     'min_temperature': {
 |       'value': '3',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '7',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '50',
 |     'wind': {
 |       'avg_speed': '2',
 |       'max_speed': '5',
 |       'units': 'meters_per_second',
 |       'direction': 'WNW',
 |       'high_wind_warning': '0'
 |     }
 |   },
 |   'evening': {
 |     'conditions': 'mostly_cloudy',
 |     'min_temperature': {
 |       'value': '7',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '12',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '47',
 |     'wind': {
 |       'avg_speed': '3',
 |       'max_speed': '7',
 |       'units': 'meters_per_second',
 |       'direction': 'W',
 |       'high_wind_warning': '0'
 |     }
 |   },
 |   'night': {
 |     'conditions': 'partly_cloudy',
 |     'min_temperature': {
 |       'value': '2',
 |       'units': 'degrees_celsius'
 |     },
 |     'max_temperature': {
 |       'value': '5',
 |       'units': 'degrees_celsius'
 |     },
 |     'humidity': '40',
 |     'wind': {
 |       'avg_speed': '5',
 |       'max_speed': '10',
 |       'units': 'meters_per_second',
 |       'direction': 'W',
 |       'high_wind_warning': '0'
 |     }
 |   }
 | }
 */

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.