Commit 215130e3 authored by Tomáš Jakubec's avatar Tomáš Jakubec
Browse files

automatic traits algorithms.

To achieve the maximal efficiency of traits approach is necessary to
change name type from std::string to const char*.
Moreover, I had to make the default trait public in another way. There
is a function creating and returning the generated Trait. At first sight
is seemed to me as bad idea, but the compiler can not work so
efficiently with it. Thus, it is better to have static function which
generates the object of traits.
parent d2a1f3b3
This diff is collapsed.
......@@ -17,6 +17,7 @@ HEADERS += \
../src/NumericStaticArray/InlineArrayOperations.h \
../src/Traits/CustomTypeTraits.h \
../src/Traits/MemberApproach/MemberApproach.h \
../src/Traits/TraitsAlgorithm/TraitsAlgorithm.h \
../src/UnstructuredMesh/MeshDataContainer/MeshDataContainer.h \
../src/UnstructuredMesh/MeshDataContainer/MeshDataIO/VTKMeshDataReader.h \
../src/UnstructuredMesh/MeshDataContainer/MeshDataIO/VTKMeshDataWriter.h \
......
......@@ -25,9 +25,25 @@ public:
template<typename MSGTYPE>
static void writeMessage(const char* prefix, int line, const char* sourceFile, const MSGTYPE& message) {
#ifdef CONSOLE_COLORED_OUTPUT
#ifdef _WIN32
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
std::cerr << prefix << " " << sourceFile << " << " << line << " >> ==> ";
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
VariableExport<>::exportVariable(std::cerr, message);
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
std::cerr << " <==\n";
#else
std::cerr << prefix << " " << sourceFile << " << " << line << " >> ==> \033[0;32m";
VariableExport<>::exportVariable(std::cerr, message);
std::cerr << "\033[0m <==\n";
#endif
#else
std::cerr << prefix << " " << sourceFile << " << " << line << " >> ==> ";
VariableExport<>::exportVariable(std::cerr, message);
std::cerr << " <==\n";
#endif
}
template<typename VAR_NAME, typename VAR, typename ... REST>
......
#ifndef DEBUG_H
#define DEBUG_H
#ifndef UNDEBUG
#include "../Macros/MacroForEach.h"
#include <iostream>
......
......@@ -181,9 +181,9 @@ struct VariableExport {
};
template<typename T, unsigned int Index>
struct PrintClass<T, Index, typename std::enable_if<Index == Traits<T>::ttype::size() - 1>::type>{
struct PrintClass<T, Index, typename std::enable_if<Index == Traits<T>::traitsType::size() - 1>::type>{
static void print(std::ostream& ost, const T &traitedClass){
ost << '"' << Traits<T>::tr.template getName<Traits<T>::ttype::size() - 1>() << "\" : ";
ost << '"' << Traits<T>::tr.template getName<Traits<T>::traitsType::size() - 1>() << "\" : ";
VariableExport::exportVariable(ost, Traits<T>::tr.template getValue<Traits<T>::tr.size() - 1>(traitedClass));
}
};
......@@ -196,7 +196,7 @@ struct VariableExport {
>::type
{
ost << "{ ";
PrintClass<typename DefaultIOTraits<T>::ttype>::print(ost, traitedClass);
PrintClass<typename DefaultIOTraits<T>::traitsType>::print(ost, traitedClass);
ost << " }";
}
......@@ -359,8 +359,8 @@ struct VariableExport<VARIABLE_EXPORT_METHOD::stdio> {
struct PrintClass{
static std::string print(const T &traitedClass){
std::string res;
res += '"' + Traits<T>::ttype::template getName<Index>() + "\" : ";
VariableExport::exportVariable(Traits<T>::ttype::template getReference<Index>()->getValue(traitedClass));
res += '"' + Traits<T>::traitsType::template getName<Index>() + "\" : ";
VariableExport::exportVariable(Traits<T>::traitsType::template getReference<Index>()->getValue(traitedClass));
res += ", ";
res += PrintClass<T, Index + 1>::print( traitedClass);
return res;
......@@ -390,11 +390,11 @@ struct VariableExport<VARIABLE_EXPORT_METHOD::stdio> {
};
template<typename T, unsigned int Index>
struct PrintClass<T, Index, typename std::enable_if<Index == Traits<T>::ttype::size() - 1>::type>{
struct PrintClass<T, Index, typename std::enable_if<Index == Traits<T>::traitsType::size() - 1>::type>{
static std::string print(const T &traitedClass){
std::string res;
res += '"' + Traits<T>::ttype::template getName<Traits<T>::ttype::size() - 1>() + "\" : ";
VariableExport::exportVariable(Traits<T>::ttype::template getReference<Traits<T>::ttype::size() - 1>()->getValue(traitedClass));
res += '"' + Traits<T>::traitsType::template getName<Traits<T>::traitsType::size() - 1>() + "\" : ";
VariableExport::exportVariable(Traits<T>::traitsType::template getReference<Traits<T>::traitsType::size() - 1>()->getValue(traitedClass));
return res;
}
};
......@@ -409,7 +409,7 @@ struct VariableExport<VARIABLE_EXPORT_METHOD::stdio> {
{
std::string res;
res += "{ ";
res += PrintClass<typename DefaultIOTraits<T>::ttype>::print(traitedClass);
res += PrintClass<typename DefaultIOTraits<T>::traitsType>::print(traitedClass);
res += " }";
return res;
}
......
......@@ -32,8 +32,8 @@ template <typename Class, typename ValueType>
class MemberReference<Class, ValueType, ValueType Class::*> : public MemberApproach<Class, ValueType>{
using refType = ValueType Class::*;
public:
refType const ref;
const refType ref;
public:
......@@ -41,6 +41,10 @@ public:
//ref = referenceToMember;
}
MemberReference(const MemberReference<Class, ValueType, ValueType Class::*>&) = default;
MemberReference(MemberReference<Class, ValueType, ValueType Class::*>&&) = default;
virtual ValueType getValue(const Class* c) const override {
return c->*ref;
}
......@@ -56,6 +60,10 @@ public:
virtual void setValue(Class& c, const ValueType& val) const override {
c.*ref = val;
}
ValueType& getAttr(Class& c) const {
return c.*ref;
}
};
......
......@@ -14,23 +14,27 @@ public:
template <unsigned int Index>
using type = typename MemberReferenceType<refType<Index>>::type;
private:
template<unsigned int Index>
using memRefType = MemberReference<Class, type<Index>, refType<Index>>;
template<unsigned int Index = 0, typename Dummy = void>
struct MemRefs: public MemRefs<Index + 1> {
const MemberReference<Class, type<Index>, refType<Index>> ref;
std::string name;
const char* name;
template <typename ... REST>
MemRefs(std::string n, refType<Index> r, REST... rest) : MemRefs<Index + 1> (rest...), ref(r), name(n){}
MemRefs(const char* n, refType<Index> r, REST... rest) : MemRefs<Index + 1> (rest...), ref(r), name(n){}
};
template<typename Dummy>
struct MemRefs<sizeof...(RefTypes) - 1, Dummy>{
const MemberReference<Class, type<sizeof...(RefTypes) - 1>, refType<sizeof...(RefTypes) - 1>> ref;
std::string name;
const char* name;
MemRefs(std::string n, refType<sizeof...(RefTypes) - 1> r) : ref(r), name(n){}
MemRefs(const char* n, refType<sizeof...(RefTypes) - 1> r) : ref(r), name(n){}
};
const MemRefs<0, void> refs;
......@@ -45,7 +49,7 @@ public:
template<unsigned int Index>
const MemberReference<Class, type<Index>, refType<Index>>& getReference() const {
MemberReference<Class, type<Index>, refType<Index>>const getReference() const {
return refs.MemRefs<Index, void>::ref;
}
......@@ -71,7 +75,7 @@ public:
template<unsigned int Index>
const std::string& getName() const {
const char* getName() const {
return refs.MemRefs<Index, void>::name;
}
......@@ -89,11 +93,7 @@ private:
-> typename std::enable_if<std::is_assignable<
std::function<
void(unsigned int,
std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<Index>
>>&,
memRefType<Index>&,
const std::string&
)
>, Functor>::value>::type
......@@ -102,11 +102,7 @@ private:
static_assert (std::is_assignable<
std::function<
void(unsigned int,
std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<Index>
>>&,
memRefType<Index>&,
const std::string&
)
>, Functor>::value, "");
......@@ -121,11 +117,8 @@ private:
static auto apply (const ThisTrait& trait, Functor f)
-> typename std::enable_if<std::is_assignable<
std::function<
void(std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<Index>
>>&,
void(
memRefType<Index>&,
const std::string&
)
>, Functor>::value>::type
......@@ -133,11 +126,8 @@ private:
static_assert (std::is_assignable<
std::function<
void(std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<Index>
>>&,
void(
memRefType<Index>&,
const std::string&
)
>, Functor>::value, "");
......@@ -154,11 +144,7 @@ private:
static_assert (std::is_assignable<
std::function<
void(unsigned int,
MemberReference<
Class,
typename ThisTrait::template type<Index>,
typename ThisTrait::template refType<Index>
>&,
memRefType<Index>&,
const std::string&
)
>, Functor<Class, typename ThisTrait::template type<Index>>>::value, "");
......@@ -179,11 +165,7 @@ private:
-> typename std::enable_if<std::is_assignable<
std::function<
void(unsigned int,
std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<ThisTrait::size() - 1>
>>&,
memRefType<size() - 1>&,
const std::string&
)
>, Functor>::value>::type
......@@ -192,11 +174,7 @@ private:
static_assert (std::is_assignable<
std::function<
void(unsigned int,
std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<ThisTrait::size() - 1>
>>&,
memRefType<size() - 1>&,
const std::string&
)
>, Functor>::value, "");
......@@ -211,11 +189,8 @@ private:
static auto apply (const ThisTrait& trait, Functor f)
-> typename std::enable_if<std::is_assignable<
std::function<
void(std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<ThisTrait::size() - 1>
>>&,
void(
memRefType<size() - 1>&,
const std::string&
)
>, Functor>::value>::type
......@@ -223,11 +198,8 @@ private:
static_assert (std::is_assignable<
std::function<
void(std::unique_ptr<
MemberApproach<
Class,
typename ThisTrait::template type<ThisTrait::size() - 1>
>>&,
void(
memRefType<size() - 1>&,
const std::string&
)
>, Functor>::value, "");
......@@ -244,12 +216,7 @@ private:
static_assert (std::is_assignable<
std::function<
void(unsigned int,
MemberReference<
Class,
typename ThisTrait::template type<ThisTrait::size() - 1>,
typename ThisTrait::template refType<ThisTrait::size() - 1>
>&,
memRefType<size() - 1>&,
const std::string&
)
>, Functor<Class, typename ThisTrait::template type<ThisTrait::size() - 1>>>::value, "");
......@@ -265,7 +232,7 @@ public:
* This function automatically
* applies a lambda with specified
* arguments: <BR> (unsigned int,
* const auto& [as const std::unique_ptr<MemberApproach<Class, typename>>&]
* const auto& [as const MemberApproach<Class, typename>&]
* const std::string&)
*/
template<typename Functor>
......@@ -310,13 +277,10 @@ template<> \
class TraitName<Class>{ \
public: \
static constexpr std::true_type is_specialized{}; \
using ttype = ::Traits<Class, FOR_EACH_2ARGS(IMPL_MEMREF_TYPE_CUSTOM, __VA_ARGS__)>; \
const static ttype tr; \
TraitName() = delete; \
static const ttype& getTraits() {return tr;} \
static constexpr unsigned int size() {return ttype::size();}\
}; \
const TraitName<Class>::ttype TraitName<Class>::tr(__VA_ARGS__); \
using traitsType = ::Traits<Class, FOR_EACH_2ARGS(IMPL_MEMREF_TYPE_CUSTOM, __VA_ARGS__)>; \
static const traitsType getTraits() {return traitsType(__VA_ARGS__);} \
static constexpr unsigned int size() {return traitsType::size();}\
};
......
#ifndef TRAITSALGORITHM_H
#define TRAITSALGORITHM_H
#include "../Traits.h"
#include "../CustomTypeTraits.h"
#include <limits>
/*
operators for arithmetic traits
*/
struct AddProcesor {
template<typename TraitT, unsigned int Index = 0>
inline static
typename std::enable_if<(Index < DefaultArithmeticTraits<TraitT>::size() - 1)>::type
exec(TraitT& op1, const TraitT& op2){
DefaultArithmeticTraits<TraitT>::getTraits().template getReference<Index>().getAttr(op1) +=
DefaultArithmeticTraits<TraitT>::getTraits().template getReference<Index>().getValue(op2);
AddProcesor::exec<TraitT, Index + 1>(op1, op2);
}
template<typename TraitT, unsigned int Index = 0>
inline static
typename std::enable_if<(Index == DefaultArithmeticTraits<TraitT>::size() - 1)>::type
exec(TraitT& op1, const TraitT& op2){
DefaultArithmeticTraits<TraitT>::getTraits().template getReference<Index>().getAttr(op1) +=
DefaultArithmeticTraits<TraitT>::getTraits().template getReference<Index>().getValue(op2);
}
};
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type&
operator+=(TraitT& op1, const TraitT& op2) noexcept {
AddProcesor::exec(op1, op2);
return op1;
}
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator+(const TraitT& op1, const TraitT& op2) noexcept {
TraitT res(op1);
return operator+=(res, op2);
}
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator+(const TraitT& op1, TraitT&& op2) noexcept {
return op2 += op1;
}
/*
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator+(TraitT&& op1, const TraitT& op2) noexcept {
return op1 += op2;
}
*/
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type&
operator-=(TraitT& op1, const TraitT& op2) noexcept {
DefaultArithmeticTraits<TraitT>::getTraits().apply(
[&op1, &op2](unsigned int, const auto& ref, const std::string&) noexcept {
ref.setValue(op1, ref.getValue(op1) - ref.getValue(op2));
}
);
return op1;
}
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator-(const TraitT& op1, const TraitT& op2) noexcept {
TraitT res(op1);
return operator-=(res, op2);
}
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator-(const TraitT& op1, TraitT&& op2) noexcept {
return op2 -= op1;
}
/*
template <typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator-(TraitT&& op1, const TraitT& op2) noexcept {
return op1 -= op2;
}
*/
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator*(const Real& op1, const TraitT& op2) noexcept {
TraitT res(op2);
return operator*=(res, op1);
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator*(const TraitT& op1, const Real& op2) noexcept {
TraitT res(op1);
return operator*=(res, op2);
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator*(const Real& op1, TraitT&& op2) noexcept {
return operator*=(op2, op1);
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator*(TraitT&& op1, const Real& op2) noexcept {
return operator*=(op1, op2);
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type&
operator*=(TraitT& op1, const Real& op2) noexcept {
DefaultArithmeticTraits<TraitT>::getTraits().apply(
[&op1, &op2](unsigned int, const auto& ref, const std::string&) noexcept {
ref.setValue(op1, ref.getValue(op1) * op2);
}
);
return op1;
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator/(const Real& op1, const TraitT& op2) noexcept {
return (1.0/op1) * op2;
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator/(const TraitT& op1, const Real& op2) noexcept {
return (1.0/op2) * op1;
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator/(const Real& op1, TraitT&& op2) noexcept {
return (1.0/op1) * op2;
}
template <typename Real, typename TraitT>
typename std::enable_if<HasDefaultArithmeticTraits<TraitT>::value, TraitT>::type
operator/(TraitT&& op1, const Real& op2) noexcept {
return (1.0/op2) * op1;
}
template<typename Trait, typename Void = void>
class TraitCommonType
{
public:
using type = void;
};
/*
template<typename Trait>
class TraitCommonType
<
Trait,
typename std::enable_if<
HasDefaultArithmeticTraits<Trait>::value &&
DefaultArithmeticTraits<Trait>::traitType::size() == 1
>::type
>
{
public:
using type = typename DefaultArithmeticTraits<Trait>::template type<0>;
};*/
template<typename Trait>
class TraitCommonType<Trait,
typename std::enable_if<HasDefaultArithmeticTraits<Trait>::value /*&&(DefaultArithmeticTraits<Trait>::traitType::size() > 1)*/>::type
>
{
using traitType = DefaultArithmeticTraits<Trait>;
template<unsigned int Index = 0, typename Void = void, typename Dummy = void>
struct declComonType{
static_assert (sizeof (Void) != 0, "Tudy vlastne chci projit");
using type = typename std::common_type<typename declComonType<Index + 1>::type, typename traitType::template type<Index>>::type;
};
/*template<unsigned int Index, typename Dummy>
struct declComonType<Index,
typename std::enable_if<HasDefaultArithmeticTraits<typename traitType::template type<Index>>::value>::type,
Dummy>{
using type = typename std::common_type<typename TraitCommonType<typename traitType::template type<Index>>::type, typename declComonType<Index + 1>::type>::type;
};*/
template<typename Dummy>
struct declComonType<traitType::traitType::size() - 1,
typename std::enable_if<!HasDefaultArithmeticTraits<typename traitType::template type<traitType::traitType::size() - 1>>::value>::type
, Dummy>{
static_assert (sizeof(Dummy) != 0, "Tudy vlastne chci projit");
using type = typename traitType::template type<traitType::traitType::size() - 1>;
};
/*
template<typename Dummy>
struct declComonType<traitType::traitType::size() - 1,
typename std::enable_if<HasDefaultArithmeticTraits<typename traitType::template type<traitType::traitType::size() - 1>>::value>::type,
Dummy>{
using type = typename TraitCommonType<typename traitType::template type<traitType::traitType::size() - 1>>::type;
};
*/
public:
using type = typename declComonType<>::type;
};
template <typename T>
typename std::enable_if<
!std::is_class<T>::value,
T
>::type