Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature functional tooling start #74

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ AddHeaderFile("ContainerTools.h")
AddHeaderFile("CountedPtr.h")
AddHeaderFile("CommandLine.h")
AddHeaderFile("FlatMap.h")
AddHeaderFile("FunctionalExtras.h")
#AddHeaderFile("FunctionalFunctors.h")
AddHeaderFile("FunctionalFunctorsContainerToContainer.h")
AddHeaderFile("FunctionalFunctorsContainerToData.h")
AddHeaderFile("FunctionalPipe.h")
AddHeaderFile("FunctionalTools.h")
AddHeaderFile("Introspection.h")
AddHeaderFile("ManagedArray.h")
Expand All @@ -169,7 +174,6 @@ ShowList("Header Files:" "\t" "${FoundationHeaderFiles}")
AddSourceFile("Base64.cpp")
AddSourceFile("BinaryBuffer.cpp")
AddSourceFile("CommandLine.cpp")
AddSourceFile("FunctionalTools.cpp")
AddSourceFile("MurmurHash.cpp")
AddSourceFile("StreamLogging.cpp")
AddSourceFile("StringTools.cpp")
Expand Down
191 changes: 189 additions & 2 deletions include/ContainerTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,96 @@ namespace ContainerDetect {
constexpr Boole HasEnd()
{ return HasEnd_t<Class>::value; }

/// @brief Convenience type for rbegin function detection.
/// @tparam Class The class to test.
template<typename Class>
using RBeginFunct_t = decltype(std::declval<Class&>().rbegin());
/// @brief Type for is_detected that tests for the existence of rbegin on a class.
/// @tparam Class The class that will be checked for the presence of a rbegin function.
template<typename Class>
using HasRBegin_t = std::is_detected<RBeginFunct_t,Class>;
/// @brief Convenience function for the value of a HasRBegin check.
/// @tparam Class The class that will be checked for the presence of a "rbegin()" function.
/// @return Returns true if the provided type has a "rbegin()" member function, false otherwise.
template<typename Class>
constexpr Boole HasRBegin()
{ return HasRBegin_t<Class>::value; }

/// @brief Convenience type for rend function detection.
/// @tparam Class The class to test.
template<typename Class>
using REndFunct_t = decltype(std::declval<Class&>().rend());
/// @brief Type for is_detected that tests for the existence of rend on a class.
/// @tparam Class The class that will be checked for the presence of a rend function.
template<typename Class>
using HasREnd_t = std::is_detected<REndFunct_t,Class>;
/// @brief Convenience function for the value of a HasREnd check.
/// @tparam Class The class that will be checked for the presence of a "rend()" function.
/// @return Returns true if the provided type has a "rend()" member function, false otherwise.
template<typename Class>
constexpr Boole HasREnd()
{ return HasREnd_t<Class>::value; }

/// @brief Convenience type for cbegin function detection.
/// @tparam Class The class to test.
template<typename Class>
using CBeginFunct_t = decltype(std::declval<Class&>().cbegin());
/// @brief Type for is_detected that tests for the existence of cbegin on a class.
/// @tparam Class The class that will be checked for the presence of a cbegin function.
template<typename Class>
using HasCBegin_t = std::is_detected<CBeginFunct_t,Class>;
/// @brief Convenience function for the value of a HasCBegin check.
/// @tparam Class The class that will be checked for the presence of a "cbegin()" function.
/// @return Returns true if the provided type has a "cbegin()" member function, false otherwise.
template<typename Class>
constexpr Boole HasCBegin()
{ return HasCBegin_t<Class>::value; }

/// @brief Convenience type for cend function detection.
/// @tparam Class The class to test.
template<typename Class>
using CEndFunct_t = decltype(std::declval<Class&>().cend());
/// @brief Type for is_detected that tests for the existence of cend on a class.
/// @tparam Class The class that will be checked for the presence of a cend function.
template<typename Class>
using HasCEnd_t = std::is_detected<CEndFunct_t,Class>;
/// @brief Convenience function for the value of a HasCEnd check.
/// @tparam Class The class that will be checked for the presence of a "cend()" function.
/// @return Returns true if the provided type has a "cend()" member function, false otherwise.
template<typename Class>
constexpr Boole HasCEnd()
{ return HasCEnd_t<Class>::value; }

/// @brief Convenience type for crbegin function detection.
/// @tparam Class The class to test.
template<typename Class>
using CRBeginFunct_t = decltype(std::declval<Class&>().crbegin());
/// @brief Type for is_detected that tests for the existence of rbegin on a class.
/// @tparam Class The class that will be checked for the presence of a rbegin function.
template<typename Class>
using HasCRBegin_t = std::is_detected<CRBeginFunct_t,Class>;
/// @brief Convenience function for the value of a HasCRBegin check.
/// @tparam Class The class that will be checked for the presence of a "crbegin()" function.
/// @return Returns true if the provided type has a "crbegin()" member function, false otherwise.
template<typename Class>
constexpr Boole HasCRBegin()
{ return HasCRBegin_t<Class>::value; }

/// @brief Convenience type for crend function detection.
/// @tparam Class The class to test.
template<typename Class>
using CREndFunct_t = decltype(std::declval<Class&>().crend());
/// @brief Type for is_detected that tests for the existence of crend on a class.
/// @tparam Class The class that will be checked for the presence of a crend function.
template<typename Class>
using HasCREnd_t = std::is_detected<CREndFunct_t,Class>;
/// @brief Convenience function for the value of a HasCREnd check.
/// @tparam Class The class that will be checked for the presence of a "crend()" function.
/// @return Returns true if the provided type has a "crend()" member function, false otherwise.
template<typename Class>
constexpr Boole HasCREnd()
{ return HasCREnd_t<Class>::value; }

/// @brief Convenience type for size function detection.
/// @tparam Class The class to test.
template<typename Class>
Expand Down Expand Up @@ -203,6 +293,54 @@ namespace ContainerDetect {
constexpr Boole HasValueType()
{ return HasValueType_t<Class>::value; }

/// @brief Dummy/failure type for detecting if a class has a "size_type" defined.
/// @tparam Class The class to be tested.
template<typename Class, typename = void>
struct DetectSizeType : std::false_type
{ };
/// @brief Success type for detecting if a class has a "size_type" defined.
/// @tparam Class The class to be tested.
template<typename Class>
struct DetectSizeType<Class,std::void_t<typename Class::size_type>> : std::true_type
{ };
/// @brief Type for detecting the existance of a "size_type" member on a class.
/// @tparam Class The class to be tested.
template<typename Class>
using HasSizeType_t = DetectSizeType<Class>;
/// @brief Convenience function for the value of a HasSizeType check.
/// @tparam Class The class that will be checked for the presence of a "size_type" member.
/// @return Returns true if the provided type has a "size_type" member, false otherwise.
template<typename Class>
constexpr Boole HasSizeType()
{ return HasSizeType_t<Class>::value; }


/// @brief Dummy/failure type for detecting if a class has a "difference_type" defined.
/// @tparam Class The class to be tested.
template<typename Class, typename = void>
struct DetectDifferenceType : std::false_type
{ };
/// @brief Success type for detecting if a class has a "difference_type" defined.
/// @tparam Class The class to be tested.
template<typename Class>
struct DetectDifferenceType<Class,std::void_t<typename Class::difference_type>> : std::true_type
{ };
/// @brief Type for detecting the existance of a "difference_type" member on a class.
/// @tparam Class The class to be tested.
template<typename Class>
using HasDifferenceType_t = DetectDifferenceType<Class>;
/// @brief Convenience function for the value of a HasDifferenceType check.
/// @tparam Class The class that will be checked for the presence of a "difference_type" member.
/// @return Returns true if the provided type has a "difference_type" member, false otherwise.
template<typename Class>
constexpr Boole HasDifferenceType()
{ return HasDifferenceType_t<Class>::value; }

// has size_type
// has difference_type



/// @brief Dummy/failure type for detecting if a class has a "key_type" defined.
/// @tparam Class The class to be tested.
template<typename Class, typename = void>
Expand Down Expand Up @@ -261,6 +399,51 @@ namespace ContainerDetect {
constexpr Boole IsRange()
{ return is_range<CheckType>::value; }

/// @brief A type trait that checks to see if a type is/has a reverse range of elements.
/// @tparam CheckType The type that will be checked.
/// @remarks This tests for the presence of rbegin() and rend() member functions on the type.
template<typename CheckType>
struct is_reverse_range :
std::bool_constant< ContainerDetect::HasRBegin<CheckType>() &&
ContainerDetect::HasREnd<CheckType>() >
{ };
/// @brief Convenience function for getting just the bool of a is_reverse_range check.
/// @tparam CheckType The type that will be checked.
/// @return Returns true if CheckType has "rbegin()" and "rend()" member functions, false otherwise.
template<typename CheckType>
constexpr Boole IsReverseRange()
{ return is_reverse_range<CheckType>::value; }

/// @brief A type trait that checks to see if a type is/has a const range of elements.
/// @tparam CheckType The type that will be checked.
/// @remarks This tests for the presence of cbegin() and cend() member functions on the type.
template<typename CheckType>
struct is_const_range :
std::bool_constant< ContainerDetect::HasCBegin<CheckType>() &&
ContainerDetect::HasCEnd<CheckType>() >
{ };
/// @brief Convenience function for getting just the bool of a is_const_range check.
/// @tparam CheckType The type that will be checked.
/// @return Returns true if CheckType has "cbegin()" and "cend()" member functions, false otherwise.
template<typename CheckType>
constexpr Boole IsConstRange()
{ return is_const_range<CheckType>::value; }

/// @brief A type trait that checks to see if a type is/has a const reverse range of elements.
/// @tparam CheckType The type that will be checked.
/// @remarks This tests for the presence of crbegin() and crend() member functions on the type.
template<typename CheckType>
struct is_const_reverse_range :
std::bool_constant< ContainerDetect::HasCRBegin<CheckType>() &&
ContainerDetect::HasCREnd<CheckType>() >
{ };
/// @brief Convenience function for getting just the bool of a is_const_reverse_range check.
/// @tparam CheckType The type that will be checked.
/// @return Returns true if CheckType has "crbegin()" and "crend()" member functions, false otherwise.
template<typename CheckType>
constexpr Boole IsConstReverseRange()
{ return is_const_reverse_range<CheckType>::value; }

/// @brief A type trait that checks to see if a type has contiguous internal storage that can be resized.
/// @tparam CheckType The type that will be checked.
/// @remarks This tests for the presence of resize() and reserve() member functions on the type.
Expand Down Expand Up @@ -307,6 +490,12 @@ namespace ContainerDetect {
constexpr Boole IsContainer()
{ return is_container<CheckType>::value; }







/// @brief Dummy/failure type for detecting if a class is a key/value pair for associative containers.
/// @tparam ValueType The value_type stored by the container being tested.
/// @remarks This is used by the is_associative_container_impl struct as a failure case when testing a
Expand Down Expand Up @@ -407,8 +596,6 @@ namespace ContainerDetect {
struct comp_is_transparent<Comp,KeyType,std::void_t<typename Comp::is_transparent>> : std::true_type
{ };



}//Mezzanine

#endif // Mezz_Foundation_ContainerTools_h
2 changes: 1 addition & 1 deletion include/FlatMap.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// © Copyright 2010 - 2019 BlackTopp Studios Inc.
// © Copyright 2010 - 2020 BlackTopp Studios Inc.
/* This file is part of The Mezzanine Engine.

The Mezzanine Engine is free software: you can redistribute it and/or modify
Expand Down
133 changes: 133 additions & 0 deletions include/FunctionalExtras.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// © Copyright 2010 - 2020 BlackTopp Studios Inc.
/* This file is part of The Mezzanine Engine.

The Mezzanine Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

The Mezzanine Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
*/
/* The original authors have included a copy of the license specified above in the
'Docs' folder. See 'gpl.txt'
*/
/* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
Build professional software and charge for their product.

However there are some practical restrictions, so if your project involves
any of the following you should contact us and we will try to work something
out:
- DRM or Copy Protection of any kind(except Copyrights)
- Software Patents You Do Not Wish to Freely License
- Any Kind of Linking to Non-GPL licensed Works
- Are Currently In Violation of Another Copyright Holder's GPL License
- If You want to change our code and not add a few hundred MB of stuff to
your distribution

These and other limitations could cause serious legal problems if you ignore
them, so it is best to simply contact us or the Free Software Foundation, if
you have any questions.

Joseph Toppi - [email protected]
John Blackwood - [email protected]
*/
#ifndef Mezz_Foundation_FunctionalExtras_h
#define Mezz_Foundation_FunctionalExtras_h

/// @file
/// @brief Tools that relate to the core functional tools but are core to the Pipe >> Functor >> Drain pattern.

#ifndef SWIG
#include "ContainerTools.h"
#include "MezzException.h"
#endif

namespace Mezzanine
{
namespace Functional
{

SAVE_WARNING_STATE
SUPPRESS_CLANG_WARNING("-Wpadded")
SUPPRESS_GCC_WARNING("-Wpadded")

/// @brief This binds value(s) to the left arguments in a function and returns a function that accepts unbound args.
/// @detailts Currying is "partially applying arguments to a function". These are ways make new functions by
/// bundling old functions and values in to a lambda so that we get new semantics. The tests have a super simple
/// example.
/// @n @n
/// Derived from https://stackoverflow.com/questions/152005/how-can-currying-be-done-in-c
/// With written permission via cc by-sa
/// @tparam FunctionType What was the passed function's type, derived automatically most of th time.
/// @tparam ArgumentsType A pack type of whatever args were passed.
/// @param Function The actual function to have data attached to it.
/// @param Arguments The data to attach to the function
/// @return A functions with 0 or more parameters bound to passed values
template<typename FunctionType, typename... ArgumentsType>
auto Curry(FunctionType Function, ArgumentsType... Arguments) {
return [=](auto... AppendedArguments) {
return std::invoke(Function, Arguments..., AppendedArguments...);
};
}

/// @copydoc Curry
/// @brief As Curry, but binds the rightmost arguments.
template<typename FunctionType, typename... ArgumentsType>
auto CurryBack(FunctionType Function, ArgumentsType... Arguments) {
return [=](auto... AppendedArguments) {
return std::invoke(Function, AppendedArguments..., Arguments...);
};
}

/// @brief Creates a simple range of countable values.
/// @tparam ReturnContainerType The kind of container to return, defaults to std::vector<Integer>.
/// @param First The first item in the container.
/// @param Last The item in the container if the stride doesn't skip over it.
/// @param Stride Count from First to Last by incrementing this amount.
/// @return A container with the computed values.
template<typename ReturnContainerType = std::vector<Integer>>
auto CreateRange(const typename ReturnContainerType::value_type& First,
const typename ReturnContainerType::value_type& Last,
const typename ReturnContainerType::value_type& Stride = 1)
{
using namespace ContainerDetect;

static_assert(IsContainer<ReturnContainerType>(),
"Mezzanine::CreateRange has a lie for a name, it actually only creates containers.");
static_assert(HasValueType<ReturnContainerType>(),
"Mezzanine::CreateRange expects the container to have a value_type.");
static_assert(HasPushBackValue<ReturnContainerType>() ||
HasInsertValue<ReturnContainerType>() ||
HasAddValue<ReturnContainerType>(),
"Mezzanine::ConCreateRangevert only fills containers with push_back(value_type), add(value_type) or "
"insert(value_type).");

ReturnContainerType Results;
if constexpr( HasReserve<ReturnContainerType>())
{ Results.reserve( static_cast<typename ReturnContainerType::size_type>(Last-First)); }

for(typename ReturnContainerType::value_type Counter = First; Counter<=Last; Counter+=Stride)
{
if constexpr(HasPushBackValue<ReturnContainerType>())
{ Results.push_back(Counter); }
else if constexpr(HasInsertValue<ReturnContainerType>())
{ Results.insert(Counter); }
else if constexpr(HasAddValue<ReturnContainerType>())
{ Results.add(Counter); }
}

return Results;
}

RESTORE_WARNING_STATE

} // Functional
} // Mezzanine

#endif // Include guard
Loading