#ifndef RITTER_INCLUDE_TOOLS_TAGED_VALUE_H
#define RITTER_INCLUDE_TOOLS_TAGED_VALUE_H

#include "tools/type_list.h"

namespace ritter {
namespace tools {

namespace detail {

struct value_base
{
    template <class T, class Next>
    class impl;

    template <class T>
    class impl<T,null>
    {
    public:
        explicit impl(const T& v) : value_(v) {}
        impl()                    : value_(T()) {}
    protected:
        ~impl() {}
        T value_;
    };
};

template <class T, class Base>
struct calc_base
{
    typedef typename head<Base>::result next_wrapper;
    typedef typename tail<Base>::result rest;
    typedef typename next_wrapper::impl<T,rest> result;
};

} // namespace detail

struct operators_inc
{
    template <class T, class Base>
    class impl : public detail::calc_base<T, Base>::result
    {
    public:
        explicit impl(const T& v) : detail::calc_base<T, Base>::result(v) {}
        impl() {}
        
        T& operator++() { return ++value_; }
        T operator++(int) { T temp(value_); ++value_; return temp;}
    protected:
        ~impl() {}
    };
};

template <class T, class Base>
class derive_operations : 
  public head<Base>::result::impl<T, typename insert_at_end<typename tail<Base>::result, detail::value_base>::result>
{
public:
    derive_operations(const T& value) 
     : head<Base>::result::impl<T, typename insert_at_end<typename tail<Base>::result, detail::value_base>::result>(value) {}
    derive_operations() {}
protected:
    ~derive_operations() {}
};


template <class T>
class derive_operations<T, null>
{
public:
    derive_operations(const T& value) : value_(value) {}
    derive_operations() : value_(T()) {}
protected:
    ~derive_operations() {}
    
    T value_;
};


template <class Tag, class T, class OperationList>
class taged_type : public derive_operations<T, OperationList>
{
public:
    explicit taged_type(const T& value) : derive_operations<T, OperationList>(value) {}
    taged_type() {}
    ~taged_type() {}
};


} // namespace tools
} // namespace ritter
#endif



