Commit 46a796e9 authored by Tomáš Jakubec's avatar Tomáš Jakubec
Browse files

Advance in problematics of traits on bind expression

parent 8bc9438e
Loading
Loading
Loading
Loading
+91 −0
Original line number Original line Diff line number Diff line
/*
 * A system for parsing function types
 */
#ifndef FUNCTION_TRAITS_H
#define FUNCTION_TRAITS_H
#include <tuple>
template<class F>
struct function_traits;

// function pointer
template<class R, class... Args>
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>
{};

template<class R, class... Args>
struct function_traits<R(Args...)>
{
    using return_type = R;

    static constexpr std::size_t arity = sizeof...(Args);

    template <std::size_t N>
    struct argument
    {
        static_assert(N < arity, "error: invalid parameter index.");
        using type = typename std::tuple_element<N,std::tuple<Args...>>::type;
    };

    template <std::size_t N>
    using argument_t = typename argument<N>::type;
};

// member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&,Args...)>
{};

// const member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...) const> : public function_traits<R(const C&,Args...)>
{};

// member object pointer
template<class C, class R>
struct function_traits<R(C::*)> : public function_traits<R(C&)>
{};

template<typename ...>
using void_t = void;
// body for functor is empty if the operator() ambiguos
// This happens, for example, when the F is the result of std::bind
template <class F, typename = void>
struct function_traits_body{};

template <class F>
struct function_traits_body<F, void_t<decltype(&F::operator())>>
{
    private:
        using call_type = function_traits<decltype(&F::operator())>;
    public:
        using return_type = typename call_type::return_type;

        static constexpr std::size_t arity = call_type::arity - 1;

        template <std::size_t N>
        struct argument
        {
            static_assert(N < arity, "error: invalid parameter index.");
            using type = typename call_type::template argument<N+1>::type;
        };

        template <std::size_t N>
        using argument_t = typename argument<N>::type;
};


// functor
template<class F>
struct function_traits : public function_traits_body<F>
{};

template<class F>
struct function_traits<F&> : public function_traits<F>
{};

template<class F>
struct function_traits<F&&> : public function_traits<F>
{};


#endif // FUNCTION_TRAITS_H
+283 −6
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
#define MEMBERAPPROACH_H
#define MEMBERAPPROACH_H
#include <type_traits>
#include <type_traits>
#include <utility>
#include <utility>

#include <functional>




/**
/**
@@ -64,17 +64,18 @@ struct HasConstGetAccess : public Impl::HasConstGetAccess<T> {};






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




template <typename Class, typename ValueType>
template <typename Class, typename ValueType>
class MemberAccess<ValueType Class::*> : public DirectAccess, public ConstGetAccess {
class MemberAccess<Class, ValueType Class::*, void> : public DirectAccess, public ConstGetAccess {
public:
public:
    using typeValue = ValueType;
    using typeValue = ValueType;
    using typeClass = Class;
    using typeClass = Class;
@@ -89,9 +90,9 @@ public:
        //ref = referenceToMember;
        //ref = referenceToMember;
    }
    }


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


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


    ValueType getValue(const Class* c) const {
    ValueType getValue(const Class* c) const {
        return c->*ref;
        return c->*ref;
@@ -121,7 +122,7 @@ public:







/*
template <typename Class, typename ValueType>
template <typename Class, typename ValueType>
class MemberAccess<ValueType& (Class::*)()> : public DirectAccess {
class MemberAccess<ValueType& (Class::*)()> : public DirectAccess {
public:
public:
@@ -454,5 +455,281 @@ public:
        return set(c);
        return set(c);
    }
    }
};
};
*/
// Experimental function traits approach
#include "../FunctionTraits.h"
#include <type_traits>
namespace Impl {


struct empty{};

template<class GetFunctor, typename Class = void>
struct _get: 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:

    _get(_getterType& g): get(g){};

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

    _get(_get< GetFunctor, Class >&&) = default;


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

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

template <class GetFunctor>
struct _get<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:

    _get(_getterType& g): get(g){};

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

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


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

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


template <class GetFunctor>
struct _get<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 >
{
private:

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

    _get(_getterType& g): get(g){};

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

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


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

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


template <class SetFunctor, typename Spec = void>
struct _set{
    using _setterType = SetFunctor;
private:
    const _setterType set;
public:
    _set(const _setterType& s): set(s){}


    _set(const _set<SetFunctor, Spec>&) = default;

    _set(_set<SetFunctor, Spec>&&) = default;

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

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


template<typename SetFunctor>
struct _set<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:
    _set(const _setterType& s): set(s){}


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


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

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


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


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

    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:
    _set(const _setterType& s): set(s){}



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


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

template<typename SetFunctor>
struct _set<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:
    _set(const _setterType& s): set(s){}

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


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

template<typename SetFunctor>
struct _set<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:
    _set(const _setterType& s): set(s){}



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


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

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


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

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::_get<GetFunctor>, public Impl::_set<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:

    MemberAccess(std::pair<GetFunctor, SetFunctor> getSet)
        : Impl::_get<GetFunctor>(getSet.first), Impl::_set<SetFunctor>(getSet.second)
    {}

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

    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::_get<GetFunctor, Class>, public Impl::_set<SetFunctor, Class>{
public:
    using typeValue = typename Impl::_get<GetFunctor, Class>::_typeValue;
    using typeClass = Class;

public:

    MemberAccess(std::pair<GetFunctor, SetFunctor> getSet)
        : Impl::_get<GetFunctor, Class>(getSet.first), Impl::_set<SetFunctor, Class>(getSet.second)
    {}

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

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

};




#endif // MEMBERAPPROACH_H
#endif // MEMBERAPPROACH_H
+5 −5
Original line number Original line Diff line number Diff line
@@ -17,17 +17,17 @@ public:
    using refType = typename std::tuple_element<Index,std::tuple<RefTypes...>>::type;
    using refType = typename std::tuple_element<Index,std::tuple<RefTypes...>>::type;


    template<unsigned int Index>
    template<unsigned int Index>
    using memRefType = MemberAccess<refType<Index>>;
    using memRefType = MemberAccess<Class, refType<Index>>;


    template <unsigned int Index>
    template <unsigned int Index>
    using type = typename MemberAccess<refType<Index>>::typeValue;
    using type = typename MemberAccess<Class, refType<Index>>::typeValue;


private:
private:


    template<unsigned int Index = 0, typename = void>
    template<unsigned int Index = 0, typename = void>
    struct MemRefs: public MemRefs<Index + 1> {
    struct MemRefs: public MemRefs<Index + 1> {


        const MemberAccess<refType<Index>> ref;
        const MemberAccess<Class, refType<Index>> ref;
        const char* name;
        const char* name;


        template <typename ... REST>
        template <typename ... REST>
@@ -36,7 +36,7 @@ private:


    template<typename Dummy>
    template<typename Dummy>
    struct MemRefs<sizeof...(RefTypes) - 1, Dummy>{
    struct MemRefs<sizeof...(RefTypes) - 1, Dummy>{
        const MemberAccess<refType<sizeof...(RefTypes) - 1>> ref;
        const MemberAccess<Class, refType<sizeof...(RefTypes) - 1>> ref;
        const char* name;
        const char* name;


        MemRefs(const char* n, refType<sizeof...(RefTypes) - 1> r) : ref(r), name(n){}
        MemRefs(const char* n, refType<sizeof...(RefTypes) - 1> r) : ref(r), name(n){}
@@ -67,7 +67,7 @@ public:




    template<unsigned int Index>
    template<unsigned int Index>
    const MemberAccess<refType<Index>> getReference() const {
    const MemberAccess<Class, refType<Index>> getReference() const {
        return refs.MemRefs<Index, void>::ref;
        return refs.MemRefs<Index, void>::ref;
    }
    }


+124 −0
Original line number Original line Diff line number Diff line
@@ -295,3 +295,127 @@ void square(UnstructuredMesh<2, size_t, double, Reserve...>& mesh){
    mesh.getCells().at(1).setBoundaryElementIndex(2);
    mesh.getCells().at(1).setBoundaryElementIndex(2);
    mesh.getCells().at(1).setIndex(1);
    mesh.getCells().at(1).setIndex(1);
}
}


template <typename IndexType, typename Real, unsigned int ... Reserve>
void Pyramid4D(UnstructuredMesh<4, IndexType, Real, Reserve...>& mesh3){


    mesh3.getVertices().push_back({0, {0,0,0,0}});
    mesh3.getVertices().push_back({1, {1,0,0,0}});
    mesh3.getVertices().push_back({2, {0,1,0,0}});
    mesh3.getVertices().push_back({3, {0,0,1,0}});
    mesh3.getVertices().push_back({4, {0,0,0,1}});




    size_t index = 0;
    mesh3.getEdges().push_back({index++,0,1});
    mesh3.getEdges().push_back({index++,0,2});
    mesh3.getEdges().push_back({index++,1,2});
    mesh3.getEdges().push_back({index++,0,3});
    mesh3.getEdges().push_back({index++,1,3});
    mesh3.getEdges().push_back({index++,2,3});

    mesh3.getEdges().push_back({index++,0,4});//6
    mesh3.getEdges().push_back({index++,1,4});//7
    mesh3.getEdges().push_back({index++,2,4});//8
    mesh3.getEdges().push_back({index++,3,4});//9

    // Dim 2
    index = 0;
    mesh3.template getElements<2>().push_back(index++);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(0);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(1);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(2);

    mesh3.template getElements<2>().push_back(index++);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(0);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(3);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(4);

    mesh3.template getElements<2>().push_back(index++);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(2);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(4);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(5);

    mesh3.template getElements<2>().push_back(index++);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(1);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(3);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(5);
    // postup do 4D
    mesh3.template getElements<2>().push_back(index++);//4
    mesh3.template getElements<2>().back().getSubelements().addSubelement(0);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(6);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(7);

    mesh3.template getElements<2>().push_back(index++);//5
    mesh3.template getElements<2>().back().getSubelements().addSubelement(1);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(6);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(8);

    mesh3.template getElements<2>().push_back(index++);//6
    mesh3.template getElements<2>().back().getSubelements().addSubelement(2);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(7);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(8);

    mesh3.template getElements<2>().push_back(index++);//7
    mesh3.template getElements<2>().back().getSubelements().addSubelement(3);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(6);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(9);

    mesh3.template getElements<2>().push_back(index++);//8
    mesh3.template getElements<2>().back().getSubelements().addSubelement(4);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(7);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(9);

    mesh3.template getElements<2>().push_back(index++);//9
    mesh3.template getElements<2>().back().getSubelements().addSubelement(5);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(8);
    mesh3.template getElements<2>().back().getSubelements().addSubelement(9);



    // 3D
    index = 0;
    mesh3.template getElements<3>().push_back(index++);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(0);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(1);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(2);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(3);

    mesh3.template getElements<3>().push_back(index++);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(0);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(4);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(5);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(6);

    mesh3.template getElements<3>().push_back(index++);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(1);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(4);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(7);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(8);

    mesh3.template getElements<3>().push_back(index++);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(2);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(6);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(8);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(9);

    mesh3.template getElements<3>().push_back(index++);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(3);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(5);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(7);
    mesh3.template getElements<3>().back().getSubelements().addSubelement(9);
    // 4D
    mesh3.getCells().push_back(0);

    for (auto& face : mesh3.getFaces()) {
        face.setCellIndex(0);
        face.setNextBElem((face.getIndex() + 1)%5, 0);
    }
    mesh3.getCells()[0].setBoundaryElementIndex(0);
    mesh3.updateSignature();

}
+0 −121

File changed.

Preview size limit exceeded, changes collapsed.