Commit 8a8b2721 authored by Tomáš Jakubec's avatar Tomáš Jakubec
Browse files

formatting

parent b8c5cccd
Loading
Loading
Loading
Loading
+114 −121
Original line number Diff line number Diff line
@@ -6,103 +6,114 @@
#include <type_traits>
namespace Impl {


struct empty{};
struct empty
{};

template<class GetFunctor, typename Class = void>
struct GetAccess: public ConstGetAccess{
struct GetAccess : public ConstGetAccess
{
#if __cplusplus <= 201702L // standard c++14 and older
    using _typeValue = typename std::result_of<GetFunctor(Class)>::type;
#else
    using _typeValue = typename std::invoke_result<GetFunctor, Class>::type;
#endif
    using _getterType = GetFunctor;

private:
    const _getterType get;
public:

public:
    constexpr GetAccess(const _getterType &g) : get(g){};

    constexpr GetAccess(const GetAccess<GetFunctor, Class> &) = default;

    constexpr GetAccess(GetAccess<GetFunctor, Class> &&) = default;

    inline auto getValue(const Class *c) const { return get(*c); }

    inline auto getValue(const Class* c) const {
        return get(*c);
    }

    inline auto getValue(const Class& c) const {
        return get(c);
    }
    inline auto getValue(const Class &c) const { return get(c); }
};

template<class GetFunctor>
struct GetAccess<GetFunctor, std::enable_if_t<!std::is_member_pointer<GetFunctor>::value && !std::is_bind_expression<GetFunctor>::value, void>>
: public std::conditional_t< std::is_const< std::remove_reference_t<typename function_traits< GetFunctor >::template argument< 0 >::type > >::value, ConstGetAccess, empty >
struct GetAccess<GetFunctor,
                 std::enable_if_t<!std::is_member_pointer<GetFunctor>::value
                                      && !std::is_bind_expression<GetFunctor>::value,
                                  void>>
    : public std::conditional_t<std::is_const<std::remove_reference_t<typename function_traits<
                                    GetFunctor>::template argument<0>::type>>::value,
                                ConstGetAccess,
                                empty>
{

    using _getterType = GetFunctor;

private:
    const _getterType get;
    using _getClassRef = std::remove_reference_t<typename function_traits<GetFunctor>::template argument<0>::type>;
public:
    using _getClassRef
        = std::remove_reference_t<typename function_traits<GetFunctor>::template argument<0>::type>;

public:
    constexpr GetAccess(const _getterType &g) : get(g){};

    constexpr GetAccess(const GetAccess<GetFunctor, std::enable_if_t<!std::is_member_pointer<GetFunctor>::value && !std::is_bind_expression<GetFunctor>::value, void>>&) = default;
    constexpr GetAccess(
        const GetAccess<GetFunctor,
                        std::enable_if_t<!std::is_member_pointer<GetFunctor>::value
                                             && !std::is_bind_expression<GetFunctor>::value,
                                         void>> &)
        = default;

    constexpr GetAccess(GetAccess<GetFunctor, std::enable_if_t<!std::is_member_pointer<GetFunctor>::value && !std::is_bind_expression<GetFunctor>::value, void>>&&) = default;
    constexpr GetAccess(GetAccess<GetFunctor,
                                  std::enable_if_t<!std::is_member_pointer<GetFunctor>::value
                                                       && !std::is_bind_expression<GetFunctor>::value,
                                                   void>> &&)
        = default;

    inline auto getValue(_getClassRef *c) const { return get(*c); }

    inline auto getValue(_getClassRef* c) const {
        return get(*c);
    }

    inline auto getValue(_getClassRef& c) const {
        return get(c);
    }
    inline auto getValue(_getClassRef &c) const { return get(c); }
};


template<class GetFunctor>
struct GetAccess<GetFunctor, std::enable_if_t<std::is_member_pointer<GetFunctor>::value, void>>
: public std::conditional_t< std::is_const< std::remove_reference_t<typename function_traits< GetFunctor >::template argument< 0 >::type > >::value, ConstGetAccess, empty >
    : public std::conditional_t<std::is_const<std::remove_reference_t<typename function_traits<
                                    GetFunctor>::template argument<0>::type>>::value,
                                ConstGetAccess,
                                empty>
{
private:

    using _getterType = GetFunctor;
    const _getterType get;
    using _getClassRef = std::remove_reference_t<typename function_traits<GetFunctor>::template argument<0>::type>;
public:
    using _getClassRef
        = std::remove_reference_t<typename function_traits<GetFunctor>::template argument<0>::type>;

public:
    constexpr GetAccess(const _getterType &g) : get(g){};

    constexpr GetAccess(const GetAccess<GetFunctor, std::enable_if_t<std::is_member_pointer<GetFunctor>::value, void>>&) = default;
    constexpr GetAccess(
        const GetAccess<GetFunctor,
                        std::enable_if_t<std::is_member_pointer<GetFunctor>::value, void>> &)
        = default;

    constexpr GetAccess(GetAccess<GetFunctor, std::enable_if_t<std::is_member_pointer<GetFunctor>::value, void>>&&) = default;
    constexpr GetAccess(
        GetAccess<GetFunctor, std::enable_if_t<std::is_member_pointer<GetFunctor>::value, void>> &&)
        = default;


    inline auto getValue(_getClassRef* c) const {
        return (c->*get)();
    }
    inline auto getValue(_getClassRef *c) const { return (c->*get)(); }

    /**
     * @brief Returns a value of a member of the object c.
     */
    inline auto getValue(_getClassRef& c) const {
        return (c.*get)();
    }
    inline auto getValue(_getClassRef &c) const { return (c.*get)(); }
};


template<class SetFunctor, typename Spec = void>
struct SetAccess{
struct SetAccess
{
    using _setterType = SetFunctor;

private:
    const _setterType set;
public:

public:
    constexpr SetAccess(const _setterType &s) : set(s) {}

    constexpr SetAccess(const SetAccess<SetFunctor, Spec> &) = default;
@@ -110,132 +121,114 @@ public:
    constexpr SetAccess(SetAccess<SetFunctor, Spec> &&) = default;

    template<typename typeClass, typename typeValue>
    inline void setValue(typeClass* c, const typeValue& val) const {
    inline void setValue(typeClass *c, const typeValue &val) const
    {
        set(c, val);
    }

    template<typename typeClass, typename typeValue>
    inline void setValue(typeClass& c, const typeValue& val) const {
    inline void setValue(typeClass &c, const typeValue &val) const
    {
        set(c, val);
    }
};


template<typename SetFunctor>
struct SetAccess<SetFunctor, std::enable_if_t<!std::is_member_pointer<SetFunctor>::value && function_traits<SetFunctor>::arity == 2, void>>{

struct SetAccess<SetFunctor,
                 std::enable_if_t<!std::is_member_pointer<SetFunctor>::value
                                      && function_traits<SetFunctor>::arity == 2,
                                  void>>
{
    using _typeValue = std::decay_t<typename function_traits<SetFunctor>::template argument<1>::type>;
    using _typeClass = std::decay_t<typename function_traits<SetFunctor>::template argument<0>::type>;

    using _setterType = SetFunctor;

private:
    const _setterType set;
public:

public:
    constexpr SetAccess(const _setterType &s) : set(s) {}

    inline void setValue(_typeClass* c, const _typeValue& val) const {
        set(c, val);
    }


    inline void setValue(_typeClass& c, const _typeValue& val) const {
        set(c, val);
    }

    inline void setValue(_typeClass *c, const _typeValue &val) const { set(c, val); }

    inline void setValue(_typeClass &c, const _typeValue &val) const { set(c, val); }
};


template<typename SetFunctor>
struct SetAccess<SetFunctor, std::enable_if_t<!std::is_member_pointer<SetFunctor>::value && function_traits<SetFunctor>::arity == 1, void>>
: public DirectAccess{

struct SetAccess<SetFunctor,
                 std::enable_if_t<!std::is_member_pointer<SetFunctor>::value
                                      && function_traits<SetFunctor>::arity == 1,
                                  void>> : public DirectAccess
{
    using _typeValue = std::decay_t<typename function_traits<SetFunctor>::return_type>;
    using _typeClass = std::decay_t<typename function_traits<SetFunctor>::template argument<0>::type>;

    using _setterType = SetFunctor;

private:
    const _setterType set;
public:

public:
    constexpr SetAccess(const _setterType &s) : set(s) {}

    inline void setValue(_typeClass* c, const _typeValue& val) const {
        set(c) = val;
    }
    inline void setValue(_typeClass *c, const _typeValue &val) const { set(c) = val; }

    inline void setValue(_typeClass &c, const _typeValue &val) const { set(c) = val; }

    inline void setValue(_typeClass& c, const _typeValue& val) const {
        set(c) = val;
    }
    inline auto &getAttr(_typeClass *c) const { return set(c); }

    inline auto& getAttr(_typeClass* c) const {
        return set(c);
    }


    inline auto& getAttr(_typeClass& c) const {
        return set(c);
    }
    inline auto &getAttr(_typeClass &c) const { return set(c); }
};

template<typename SetFunctor>
struct SetAccess<SetFunctor, std::enable_if_t<std::is_member_pointer<SetFunctor>::value && function_traits<SetFunctor>::arity == 2, void>>{
struct SetAccess<SetFunctor,
                 std::enable_if_t<std::is_member_pointer<SetFunctor>::value
                                      && function_traits<SetFunctor>::arity == 2,
                                  void>>
{
private:
    using _typeValue = std::decay_t<typename function_traits<SetFunctor>::template argument<1>::type>;
    using _typeClass = std::decay_t<typename function_traits<SetFunctor>::template argument<0>::type>;

    using _setterType = SetFunctor;

private:
    const _setterType set;

public:
    constexpr SetAccess(const _setterType &s) : set(s) {}

    inline void setValue(_typeClass* c, const _typeValue& val) const {
        (c->*set)(val);
    }
    inline void setValue(_typeClass *c, const _typeValue &val) const { (c->*set)(val); }


    inline void setValue(_typeClass& c, const _typeValue& val) const {
        (c.*set)(val);
    }
    inline void setValue(_typeClass &c, const _typeValue &val) const { (c.*set)(val); }
};

template<typename SetFunctor>
struct SetAccess<SetFunctor, std::enable_if_t<std::is_member_pointer<SetFunctor>::value && function_traits<SetFunctor>::arity == 1, void>>
: public DirectAccess {
struct SetAccess<SetFunctor,
                 std::enable_if_t<std::is_member_pointer<SetFunctor>::value &&
                                  function_traits<SetFunctor>::arity == 1,
                                  void>> : public DirectAccess
{
private:
    using _typeValue = std::decay_t<typename function_traits<SetFunctor>::return_type>;
    using _typeClass = std::decay_t<typename function_traits<SetFunctor>::template argument<0>::type>;

    using _setterType = SetFunctor;

private:
    const _setterType set;
public:


public:
    constexpr SetAccess(const _setterType &s) : set(s) {}

    inline void setValue(_typeClass *c, const _typeValue &val) const { (c->*set)() = val; }

    inline void setValue(_typeClass &c, const _typeValue &val) const { (c.*set)() = val; }

    inline void setValue(_typeClass* c, const _typeValue& val) const {
        (c->*set)() = val;
    }


    inline void setValue(_typeClass& c, const _typeValue& val) const {
        (c.*set)() = val;
    }
    inline auto &getAttr(_typeClass *c) const { return (c->*set)(); }

    inline auto& getAttr(_typeClass* c) const {
        return (c->*set)();
    }


    inline auto& getAttr(_typeClass& c) const {
        return (c.*set)();
    }
    inline auto &getAttr(_typeClass &c) const { return (c.*set)(); }
};
} //Impl
} // namespace Impl
#endif // GETSETACCESS_H
+56 −55
Original line number Diff line number Diff line
@@ -3,20 +3,20 @@
#include "AccessType.h"
#include "GetSetAccess.h"



template<typename Class, typename Ref, typename = void>
class MemberAccess{
class MemberAccess
{
    static_assert(!std::is_same<Ref, void>::value,
                  "The type Ref must be reference to member (ValueType Class::*),"
                  " member function or pointer to getter and setter");

public:
    constexpr MemberAccess(Ref);
};


template<typename Class, typename ValueType>
class MemberAccess<Class, ValueType Class::*, void> : public DirectAccess, public ConstGetAccess {
class MemberAccess<Class, ValueType Class::*, void> : public DirectAccess, public ConstGetAccess
{
public:
    using typeValue = ValueType;
    using typeClass = Class;
@@ -26,81 +26,82 @@ private:
    const refType mReference;

public:

    constexpr MemberAccess(const refType &referenceToMember) : mReference(referenceToMember) {}

    constexpr MemberAccess(const MemberAccess<Class, ValueType Class::*, void> &) = default;

    constexpr MemberAccess(MemberAccess<Class, ValueType Class::*, void> &&) = default;

    inline ValueType getValue(const Class* c) const {
        return c->*mReference;
    }
    inline ValueType getValue(const Class *c) const { return c->*mReference; }

    inline void setValue(Class* c, const ValueType& val) const {
        c->*mReference = val;
    }
    inline void setValue(Class *c, const ValueType &val) const { c->*mReference = val; }

    inline ValueType& getAttr(Class* c) const {
        return c->*mReference;
    }
    inline ValueType &getAttr(Class *c) const { return c->*mReference; }

    inline ValueType getValue(const Class& c) const {
        return c.*mReference;
    }
    inline ValueType getValue(const Class &c) const { return c.*mReference; }

    inline void setValue(Class& c, const ValueType& val) const {
        c.*mReference = val;
    }
    inline void setValue(Class &c, const ValueType &val) const { c.*mReference = val; }

    inline ValueType& getAttr(Class& c) const {
        return c.*mReference;
    }
    inline ValueType &getAttr(Class &c) const { return c.*mReference; }
};

// Experimental function traits approach


template<class Class, class GetFunctor, class SetFunctor>
class MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>>
: public Impl::GetAccess<GetFunctor>, public Impl::SetAccess<SetFunctor>{
class MemberAccess<Class,
                   std::pair<GetFunctor, SetFunctor>,
                   std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>>
    : public Impl::GetAccess<GetFunctor>, public Impl::SetAccess<SetFunctor>
{
public:
    using typeValue = std::decay_t<typename function_traits<GetFunctor>::return_type>;
    using typeClass = std::decay_t<typename function_traits<GetFunctor>::template argument<0>::type>;

public:

    constexpr MemberAccess(const std::pair<GetFunctor, SetFunctor> &getSet)
        : Impl::GetAccess<GetFunctor>(getSet.first), Impl::SetAccess<SetFunctor>(getSet.second)
    {}

    constexpr MemberAccess(const MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>>&) = default;

    constexpr MemberAccess(MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>>&&) = default;

    constexpr MemberAccess(
        const MemberAccess<Class,
                           std::pair<GetFunctor, SetFunctor>,
                           std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>> &)
        = default;

    constexpr MemberAccess(
        MemberAccess<Class,
                     std::pair<GetFunctor, SetFunctor>,
                     std::enable_if_t<!std::is_bind_expression<GetFunctor>::value>> &&)
        = default;
};



template<class Class, class GetFunctor, class SetFunctor>
class MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<std::is_bind_expression<GetFunctor>::value> >
: public Impl::GetAccess<GetFunctor, Class>, public Impl::SetAccess<SetFunctor>{
class MemberAccess<Class,
                   std::pair<GetFunctor, SetFunctor>,
                   std::enable_if_t<std::is_bind_expression<GetFunctor>::value>>
    : public Impl::GetAccess<GetFunctor, Class>, public Impl::SetAccess<SetFunctor>
{
public:
    using typeValue = typename Impl::GetAccess<GetFunctor, Class>::_typeValue;
    using typeClass = Class;

public:

    constexpr MemberAccess(const std::pair<GetFunctor, SetFunctor> &getSet)
        : Impl::GetAccess<GetFunctor, Class>(getSet.first), Impl::SetAccess<SetFunctor>(getSet.second)
        : Impl::GetAccess<GetFunctor, Class>(getSet.first), Impl::SetAccess<SetFunctor>(
                                                                getSet.second)
    {}

    constexpr MemberAccess(const MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<std::is_bind_expression<GetFunctor>::value> >&) = default;

    constexpr MemberAccess(MemberAccess<Class, std::pair<GetFunctor, SetFunctor>, std::enable_if_t<std::is_bind_expression<GetFunctor>::value> >&&) = default;

    constexpr MemberAccess(
        const MemberAccess<Class,
                           std::pair<GetFunctor, SetFunctor>,
                           std::enable_if_t<std::is_bind_expression<GetFunctor>::value>> &)
        = default;

    constexpr MemberAccess(
        MemberAccess<Class,
                     std::pair<GetFunctor, SetFunctor>,
                     std::enable_if_t<std::is_bind_expression<GetFunctor>::value>> &&)
        = default;
};



#endif // MEMBERAPPROACH_H
+59 −73
Original line number Diff line number Diff line
@@ -16,109 +16,95 @@
 * So far, the algorithms supports traits with direct refferences only.
*/


/**
 * @brief The TraitsBinaryExpressionProcesor struct applies
 * a binary operator on each member of a traited struct.
 */
template<template<typename, typename> class Operator>
struct TraitsBinaryExpressionProcesor {



    template<typename TraitT, unsigned int Index = 0, bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<!ApplyOperation>::type
    evaluate(TraitT& res, const TraitT& op1, const TraitT& op2){

struct TraitsBinaryExpressionProcesor
{
    template<typename TraitT,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<!ApplyOperation>::type evaluate(TraitT &res,
                                                                          const TraitT &op1,
                                                                          const TraitT &op2)
    {
        TraitsBinaryExpressionProcesor<Operator>::evaluate<TraitT, Index, true>(res, op1, op2);
        TraitsBinaryExpressionProcesor<Operator>::evaluate<TraitT, Index + 1>(res, op1, op2);

    }


    template<typename TraitT, unsigned int Index = 0, bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<ApplyOperation>::type
    evaluate(TraitT&res, const TraitT& op1,  const TraitT& op2){

        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res) =
                Operator<
                    typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>,
                    typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>
                >::evaluate(
                    DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op1),
                    DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op2)
                );

    }



    template<typename TraitT, typename Real, unsigned int Index = 0, bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<!ApplyOperation>::type
    evaluate(TraitT& res, const TraitT& op1, const Real& op2){

    template<typename TraitT,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<ApplyOperation>::type evaluate(TraitT &res,
                                                                         const TraitT &op1,
                                                                         const TraitT &op2)
    {
        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res)
            = Operator<typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>,
                       typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>>::
                evaluate(DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op1),
                         DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op2));
    }

    template<typename TraitT,
             typename Real,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<!ApplyOperation>::type evaluate(TraitT &res,
                                                                          const TraitT &op1,
                                                                          const Real &op2)
    {
        TraitsBinaryExpressionProcesor<Operator>::evaluate<TraitT, Real, Index, true>(res, op1, op2);
        TraitsBinaryExpressionProcesor<Operator>::evaluate<TraitT, Real, Index + 1>(res, op1, op2);

    }

    template<typename TraitT, typename Real, unsigned int Index = 0, bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<ApplyOperation>::type
    evaluate(TraitT&res, const TraitT& op1,  const Real& op2){

        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res) =
                Operator<
                    typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>,
                    Real
                >::evaluate(
                    DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op1),
                    op2
                );

    template<typename TraitT,
             typename Real,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<ApplyOperation>::type evaluate(TraitT &res,
                                                                         const TraitT &op1,
                                                                         const Real &op2)
    {
        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res)
            = Operator<typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>,
                       Real>::evaluate(DefaultArithmeticTraits<TraitT>::getTraits()
                                           .template getValue<Index>(op1),
                                       op2);
    }

};



/**
 * @brief The TraitsUnaryExpressionProcesor struct applies
 * a binary operator on each member of a traited struct.
 */
template<template<typename> class Operator>
struct TraitsUnaryExpressionProcesor {


    template<typename TraitT, unsigned int Index = 0,  bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<!ApplyOperation>::type
    evaluate(TraitT& res, const TraitT& op1){

struct TraitsUnaryExpressionProcesor
{
    template<typename TraitT,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<!ApplyOperation>::type evaluate(TraitT &res,
                                                                          const TraitT &op1)
    {
        TraitsUnaryExpressionProcesor<Operator>::evaluate<TraitT, Index, true>(res, op1);
        TraitsUnaryExpressionProcesor<Operator>::evaluate<TraitT, Index + 1>(res, op1);

    }

    template<typename TraitT, unsigned int Index = 0, bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static
    typename std::enable_if<ApplyOperation>::type
    evaluate(TraitT& res, const TraitT& op1){

        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res) =
            Operator<
                typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>
            >::evaluate(
                DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op1)
            );
    template<typename TraitT,
             unsigned int Index = 0,
             bool ApplyOperation = Index == DefaultArithmeticTraits<TraitT>::size() - 1>
    inline static typename std::enable_if<ApplyOperation>::type evaluate(TraitT &res,
                                                                         const TraitT &op1)
    {
        DefaultArithmeticTraits<TraitT>::getTraits().template getAttr<Index>(res)
            = Operator<typename DefaultArithmeticTraits<TraitT>::traitsType::template type<Index>>::
                evaluate(DefaultArithmeticTraits<TraitT>::getTraits().template getValue<Index>(op1));
    }
};



////
/// Addition operators
///
+56 −24

File changed.

Preview size limit exceeded, changes collapsed.