Use "if constexpr" provided by C++17

This commit is contained in:
Stephen Seo 2018-05-21 19:19:43 +09:00
parent 8f133acbc6
commit f59f78385d
3 changed files with 57 additions and 55 deletions

View file

@ -31,7 +31,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -D NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -D NDEBUG")
target_compile_features(EntityComponentSystem INTERFACE cxx_std_14) target_compile_features(EntityComponentSystem INTERFACE cxx_std_17)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Debug', none was specified.") message(STATUS "Setting build type to 'Debug', none was specified.")
@ -53,7 +53,7 @@ if(GTEST_FOUND)
add_executable(UnitTests ${UnitTests_SOURCES}) add_executable(UnitTests ${UnitTests_SOURCES})
target_link_libraries(UnitTests EntityComponentSystem ${GTEST_LIBRARIES}) target_link_libraries(UnitTests EntityComponentSystem ${GTEST_LIBRARIES})
target_include_directories(UnitTests PUBLIC ${GTEST_INCLUDE_DIR}) target_include_directories(UnitTests PUBLIC ${GTEST_INCLUDE_DIR})
target_compile_features(UnitTests PUBLIC cxx_std_14) target_compile_features(UnitTests PUBLIC cxx_std_17)
enable_testing() enable_testing()
add_test(NAME UnitTests COMMAND UnitTests) add_test(NAME UnitTests COMMAND UnitTests)

View file

@ -66,7 +66,7 @@ namespace EC
Bitset<ComponentsList, TagsList> bitset; Bitset<ComponentsList, TagsList> bitset;
EC::Meta::forEach<Contents>([&bitset] (auto t) { EC::Meta::forEach<Contents>([&bitset] (auto t) {
if(EC::Meta::Contains<decltype(t), Combined>::value) if constexpr (EC::Meta::Contains<decltype(t), Combined>::value)
{ {
bitset[EC::Meta::IndexOf<decltype(t), Combined>::value] = bitset[EC::Meta::IndexOf<decltype(t), Combined>::value] =
true; true;

View file

@ -32,7 +32,6 @@
#include "Meta/Matching.hpp" #include "Meta/Matching.hpp"
#include "Meta/ForEachWithIndex.hpp" #include "Meta/ForEachWithIndex.hpp"
#include "Meta/ForEachDoubleTuple.hpp" #include "Meta/ForEachDoubleTuple.hpp"
#include "Meta/IndexOf.hpp"
#include "Bitset.hpp" #include "Bitset.hpp"
namespace EC namespace EC
@ -67,7 +66,7 @@ namespace EC
template <typename... Types> template <typename... Types>
struct Storage struct Storage
{ {
using type = std::tuple<std::vector<Types>..., std::vector<char> >; using type = std::tuple<std::vector<Types>...>;
}; };
using ComponentsStorage = using ComponentsStorage =
typename EC::Meta::Morph<ComponentsList, Storage<> >::type; typename EC::Meta::Morph<ComponentsList, Storage<> >::type;
@ -242,15 +241,10 @@ namespace EC
template <typename Component> template <typename Component>
Component* getEntityData(const std::size_t& index) Component* getEntityData(const std::size_t& index)
{ {
constexpr auto componentIndex = EC::Meta::IndexOf< if constexpr (EC::Meta::Contains<Component, Components>::value)
Component, Components>::value;
if(componentIndex < Components::size)
{ {
// Cast required due to compiler thinking that an invalid return &std::get<std::vector<Component> >(componentsStorage)
// Component is needed even though the enclosing if statement .at(index);
// prevents this from ever happening.
return (Component*) &std::get<componentIndex>(
componentsStorage).at(index);
} }
else else
{ {
@ -295,15 +289,10 @@ namespace EC
template <typename Component> template <typename Component>
const Component* getEntityData(const std::size_t& index) const const Component* getEntityData(const std::size_t& index) const
{ {
constexpr auto componentIndex = EC::Meta::IndexOf< if constexpr (EC::Meta::Contains<Component, Components>::value)
Component, Components>::value;
if(componentIndex < Components::size)
{ {
// Cast required due to compiler thinking that an invalid return &std::get<std::vector<Component> >(componentsStorage)
// Component is needed even though the enclosing if statement .at(index);
// prevents this from ever happening.
return (Component*) &std::get<componentIndex>(
componentsStorage).at(index);
} }
else else
{ {
@ -395,27 +384,25 @@ namespace EC
template <typename Component, typename... Args> template <typename Component, typename... Args>
void addComponent(const std::size_t& entityID, Args&&... args) void addComponent(const std::size_t& entityID, Args&&... args)
{ {
if(!EC::Meta::Contains<Component, Components>::value if constexpr (!EC::Meta::Contains<Component, Components>::value)
|| !isAlive(entityID)) {
return;
}
else
{
if(!isAlive(entityID))
{ {
return; return;
} }
Component component(std::forward<Args>(args)...); Component component(std::forward<Args>(args)...);
std::get<BitsetType>( std::get<BitsetType>(
entities[entityID] entities[entityID]
).template getComponentBit<Component>() = true; ).template getComponentBit<Component>() = true;
constexpr auto index = std::get<std::vector<Component> >(componentsStorage)[entityID]
EC::Meta::IndexOf<Component, Components>::value; = std::move(component);
}
// Cast required due to compiler thinking that vector<char> at
// index = Components::size is being used, even if the previous
// if statement will prevent this from ever happening.
(*((std::vector<Component>*)(&std::get<index>(
componentsStorage
))))[entityID] = std::move(component);
} }
/*! /*!
@ -432,16 +419,21 @@ namespace EC
template <typename Component> template <typename Component>
void removeComponent(const std::size_t& entityID) void removeComponent(const std::size_t& entityID)
{ {
if(!EC::Meta::Contains<Component, Components>::value if constexpr (!EC::Meta::Contains<Component, Components>::value)
|| !isAlive(entityID)) {
return;
}
else
{
if(!isAlive(entityID))
{ {
return; return;
} }
std::get<BitsetType>( std::get<BitsetType>(
entities[entityID] entities[entityID]
).template getComponentBit<Component>() = false; ).template getComponentBit<Component>() = false;
} }
}
/*! /*!
\brief Adds the given Tag to the given Entity. \brief Adds the given Tag to the given Entity.
@ -454,16 +446,21 @@ namespace EC
template <typename Tag> template <typename Tag>
void addTag(const std::size_t& entityID) void addTag(const std::size_t& entityID)
{ {
if(!EC::Meta::Contains<Tag, Tags>::value if constexpr (!EC::Meta::Contains<Tag, Tags>::value)
|| !isAlive(entityID)) {
return;
}
else
{
if(!isAlive(entityID))
{ {
return; return;
} }
std::get<BitsetType>( std::get<BitsetType>(
entities[entityID] entities[entityID]
).template getTagBit<Tag>() = true; ).template getTagBit<Tag>() = true;
} }
}
/*! /*!
\brief Removes the given Tag from the given Entity. \brief Removes the given Tag from the given Entity.
@ -478,16 +475,21 @@ namespace EC
template <typename Tag> template <typename Tag>
void removeTag(const std::size_t& entityID) void removeTag(const std::size_t& entityID)
{ {
if(!EC::Meta::Contains<Tag, Tags>::value if constexpr (!EC::Meta::Contains<Tag, Tags>::value)
|| !isAlive(entityID)) {
return;
}
else
{
if(!isAlive(entityID))
{ {
return; return;
} }
std::get<BitsetType>( std::get<BitsetType>(
entities[entityID] entities[entityID]
).template getTagBit<Tag>() = false; ).template getTagBit<Tag>() = false;
} }
}
private: private:
template <typename... Types> template <typename... Types>