Skip to content

Commit

Permalink
Fix empty base class optimisation for aggregate skills on Windows
Browse files Browse the repository at this point in the history
The EBCO attribute on MSVC only works single inheritance. For skills
which aggregate other skills we need to explicitly enable it on each
of them.
  • Loading branch information
juliancarrivick committed May 11, 2022
1 parent 020be1e commit 9d1afc3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 10 deletions.
22 changes: 13 additions & 9 deletions include/NamedType/underlying_functionalities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ struct UnaryAddable : crtp<T, UnaryAddable>
};

template <typename T>
struct Addable : BinaryAddable<T>, UnaryAddable<T>
struct FLUENT_EBCO Addable
: BinaryAddable<T>
, UnaryAddable<T>
{
using BinaryAddable<T>::operator+;
using UnaryAddable<T>::operator+;
Expand All @@ -118,7 +120,7 @@ struct BinarySubtractable : crtp<T, BinarySubtractable>
return this->underlying();
}
};

template <typename T>
struct UnarySubtractable : crtp<T, UnarySubtractable>
{
Expand All @@ -127,14 +129,16 @@ struct UnarySubtractable : crtp<T, UnarySubtractable>
return T(-this->underlying().get());
}
};

template <typename T>
struct Subtractable : BinarySubtractable<T>, UnarySubtractable<T>
struct FLUENT_EBCO Subtractable
: BinarySubtractable<T>
, UnarySubtractable<T>
{
using UnarySubtractable<T>::operator-;
using BinarySubtractable<T>::operator-;
};

template <typename T>
struct Multiplicable : crtp<T, Multiplicable>
{
Expand Down Expand Up @@ -374,14 +378,14 @@ struct MethodCallable<NamedType<T, Parameter, Skills...>> : crtp<NamedType<T, Pa
};

template <typename NamedType_>
struct Callable
struct FLUENT_EBCO Callable
: FunctionCallable<NamedType_>
, MethodCallable<NamedType_>
{
};

template <typename T>
struct Incrementable
struct FLUENT_EBCO Incrementable
: PreIncrementable<T>
, PostIncrementable<T>
{
Expand All @@ -390,7 +394,7 @@ struct Incrementable
};

template <typename T>
struct Decrementable
struct FLUENT_EBCO Decrementable
: PreDecrementable<T>
, PostDecrementable<T>
{
Expand All @@ -399,7 +403,7 @@ struct Decrementable
};

template <typename T>
struct Arithmetic
struct FLUENT_EBCO Arithmetic
: Incrementable<T>
, Decrementable<T>
, Addable<T>
Expand Down
40 changes: 39 additions & 1 deletion test/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ TEST_CASE("UnarySubtractable constexpr")
static_assert((-s).get() == -12, "UnarySubtractable is not constexpr");
}


TEST_CASE("Multiplicable")
{
using MultiplicableType = fluent::NamedType<int, struct MultiplicableTag, fluent::Multiplicable>;
Expand Down Expand Up @@ -1135,3 +1134,42 @@ TEST_CASE("Decrementable")
CHECK( b.get() == 1 );
}
}

template <template <typename> class... Skills>
using SkilledType = fluent::NamedType<int, struct SkilledTypeTag, Skills...>;

TEST_CASE("Empty base class optimisation of skills")
{
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PreIncrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PostIncrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PreDecrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PostDecrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BinaryAddable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::UnaryAddable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Addable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BinarySubtractable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::UnarySubtractable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Subtractable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Multiplicable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Divisible>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Modulable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseInvertable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseAndable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseOrable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseXorable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseLeftShiftable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::BitWiseRightShiftable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Comparable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Dereferencable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::ImplicitlyConvertibleTo>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Printable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Hashable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::FunctionCallable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::MethodCallable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Callable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Incrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Decrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::Arithmetic>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PreIncrementable>));
CHECK(sizeof(int) == sizeof(SkilledType<fluent::PreIncrementable>));
}

0 comments on commit 9d1afc3

Please sign in to comment.