v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
667
source/core/StarAlgorithm.hpp
Normal file
667
source/core/StarAlgorithm.hpp
Normal file
|
@ -0,0 +1,667 @@
|
|||
#ifndef STAR_ALGORITHM_HPP
|
||||
#define STAR_ALGORITHM_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
|
||||
#include "StarException.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
// Function that does nothing and takes any number of arguments
|
||||
template <typename... T>
|
||||
void nothing(T&&...) {}
|
||||
|
||||
// Functional constructor call / casting.
|
||||
template <typename ToType>
|
||||
struct construct {
|
||||
template <typename... FromTypes>
|
||||
ToType operator()(FromTypes&&... fromTypes) const {
|
||||
return ToType(forward<FromTypes>(fromTypes)...);
|
||||
}
|
||||
};
|
||||
|
||||
struct identity {
|
||||
template <typename U>
|
||||
constexpr decltype(auto) operator()(U&& v) const {
|
||||
return std::forward<U>(v);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
struct SwallowReturn {
|
||||
template <typename... T>
|
||||
void operator()(T&&... args) {
|
||||
func(forward<T>(args)...);
|
||||
}
|
||||
|
||||
Func func;
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
SwallowReturn<Func> swallow(Func f) {
|
||||
return SwallowReturn<Func>{move(f)};
|
||||
}
|
||||
|
||||
struct Empty {
|
||||
bool operator==(Empty const) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator<(Empty const) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Compose arbitrary functions
|
||||
template <typename FirstFunction, typename SecondFunction>
|
||||
struct FunctionComposer {
|
||||
FirstFunction f1;
|
||||
SecondFunction f2;
|
||||
|
||||
template <typename... T>
|
||||
decltype(auto) operator()(T&&... args) {
|
||||
return f1(f2(forward<T>(args)...));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FirstFunction, typename SecondFunction>
|
||||
decltype(auto) compose(FirstFunction&& firstFunction, SecondFunction&& secondFunction) {
|
||||
return FunctionComposer<FirstFunction, SecondFunction>{move(forward<FirstFunction>(firstFunction)), move(forward<SecondFunction>(secondFunction))};
|
||||
}
|
||||
|
||||
template <typename FirstFunction, typename SecondFunction, typename ThirdFunction, typename... RestFunctions>
|
||||
decltype(auto) compose(FirstFunction firstFunction, SecondFunction secondFunction, ThirdFunction thirdFunction, RestFunctions... restFunctions) {
|
||||
return compose(forward<FirstFunction>(firstFunction), compose(forward<SecondFunction>(secondFunction), compose(forward<ThirdFunction>(thirdFunction), forward<RestFunctions>(restFunctions)...)));
|
||||
}
|
||||
|
||||
template <typename Container, typename Value, typename Function>
|
||||
Value fold(Container const& l, Value v, Function f) {
|
||||
auto i = l.begin();
|
||||
auto e = l.end();
|
||||
while (i != e) {
|
||||
v = f(v, *i);
|
||||
++i;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Like fold, but returns default value when container is empty.
|
||||
template <typename Container, typename Function>
|
||||
typename Container::value_type fold1(Container const& l, Function f) {
|
||||
typename Container::value_type res = {};
|
||||
typename Container::const_iterator i = l.begin();
|
||||
typename Container::const_iterator e = l.end();
|
||||
|
||||
if (i == e)
|
||||
return res;
|
||||
|
||||
res = *i;
|
||||
++i;
|
||||
while (i != e) {
|
||||
res = f(res, *i);
|
||||
++i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Return intersection of sorted containers.
|
||||
template <typename Container>
|
||||
Container intersect(Container const& a, Container const& b) {
|
||||
Container r;
|
||||
std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(r, r.end()));
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename MapType1, typename MapType2>
|
||||
bool mapMerge(MapType1& targetMap, MapType2 const& sourceMap, bool overwrite = false) {
|
||||
bool noCommonKeys = true;
|
||||
for (auto i = sourceMap.begin(); i != sourceMap.end(); ++i) {
|
||||
auto res = targetMap.insert(*i);
|
||||
if (!res.second) {
|
||||
noCommonKeys = false;
|
||||
if (overwrite)
|
||||
res.first->second = i->second;
|
||||
}
|
||||
}
|
||||
return noCommonKeys;
|
||||
}
|
||||
|
||||
template <typename MapType1, typename MapType2>
|
||||
bool mapsEqual(MapType1 const& m1, MapType2 const& m2) {
|
||||
if (&m1 == &m2)
|
||||
return true;
|
||||
|
||||
if (m1.size() != m2.size())
|
||||
return false;
|
||||
|
||||
for (auto const& m1pair : m1) {
|
||||
auto m2it = m2.find(m1pair.first);
|
||||
if (m2it == m2.end() || !(m2it->second == m1pair.second))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Container, typename Filter>
|
||||
void filter(Container& container, Filter&& filter) {
|
||||
auto p = std::begin(container);
|
||||
while (p != std::end(container)) {
|
||||
if (!filter(*p))
|
||||
p = container.erase(p);
|
||||
else
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutContainer, typename InContainer, typename Filter>
|
||||
OutContainer filtered(InContainer const& input, Filter&& filter) {
|
||||
OutContainer out;
|
||||
auto p = std::begin(input);
|
||||
while (p != std::end(input)) {
|
||||
if (filter(*p))
|
||||
out.insert(out.end(), *p);
|
||||
++p;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename Container, typename Cond>
|
||||
void eraseWhere(Container& container, Cond&& cond) {
|
||||
auto p = std::begin(container);
|
||||
while (p != std::end(container)) {
|
||||
if (cond(*p))
|
||||
p = container.erase(p);
|
||||
else
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container, typename Compare>
|
||||
void sort(Container& c, Compare comp) {
|
||||
std::sort(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename Container, typename Compare>
|
||||
void stableSort(Container& c, Compare comp) {
|
||||
std::stable_sort(c.begin(), c.end(), comp);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void sort(Container& c) {
|
||||
std::sort(c.begin(), c.end(), std::less<typename Container::value_type>());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void stableSort(Container& c) {
|
||||
std::stable_sort(c.begin(), c.end(), std::less<typename Container::value_type>());
|
||||
}
|
||||
|
||||
template <typename Container, typename Compare>
|
||||
Container sorted(Container const& c, Compare comp) {
|
||||
auto c2 = c;
|
||||
sort(c2, comp);
|
||||
return c2;
|
||||
}
|
||||
|
||||
template <typename Container, typename Compare>
|
||||
Container stableSorted(Container const& c, Compare comp) {
|
||||
auto c2 = c;
|
||||
sort(c2, comp);
|
||||
return c2;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
Container sorted(Container const& c) {
|
||||
auto c2 = c;
|
||||
sort(c2);
|
||||
return c2;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
Container stableSorted(Container const& c) {
|
||||
auto c2 = c;
|
||||
sort(c2);
|
||||
return c2;
|
||||
}
|
||||
|
||||
// Sort a container by the output of a computed value. The computed value is
|
||||
// only computed *once* per item in the container, which is useful both for
|
||||
// when the computed value is costly, and to avoid sorting instability with
|
||||
// floating point values. Container must have size() and operator[], and also
|
||||
// must be constructable with Container(size_t).
|
||||
template <typename Container, typename Getter>
|
||||
void sortByComputedValue(Container& container, Getter&& valueGetter, bool stable = false) {
|
||||
typedef typename Container::value_type ContainerValue;
|
||||
typedef decltype(valueGetter(ContainerValue())) ComputedValue;
|
||||
typedef std::pair<ComputedValue, size_t> ComputedPair;
|
||||
|
||||
size_t containerSize = container.size();
|
||||
|
||||
if (containerSize <= 1)
|
||||
return;
|
||||
|
||||
std::vector<ComputedPair> work(containerSize);
|
||||
for (size_t i = 0; i < containerSize; ++i)
|
||||
work[i] = {valueGetter(container[i]), i};
|
||||
|
||||
auto compare = [](ComputedPair const& a, ComputedPair const& b) { return a.first < b.first; };
|
||||
|
||||
// Sort the comptued values and the associated indexes
|
||||
if (stable)
|
||||
stableSort(work, compare);
|
||||
else
|
||||
sort(work, compare);
|
||||
|
||||
Container result(containerSize);
|
||||
for (size_t i = 0; i < containerSize; ++i)
|
||||
swap(result[i], container[work[i].second]);
|
||||
|
||||
swap(container, result);
|
||||
}
|
||||
|
||||
template <typename Container, typename Getter>
|
||||
void stableSortByComputedValue(Container& container, Getter&& valueGetter) {
|
||||
return sortByComputedValue(container, forward<Getter>(valueGetter), true);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void shuffle(Container& c) {
|
||||
std::random_shuffle(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void reverse(Container& c) {
|
||||
std::reverse(c.begin(), c.end());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
Container reverseCopy(Container c) {
|
||||
reverse(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T copy(T c) {
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
typename Container::value_type sum(Container const& cont) {
|
||||
return fold1(cont, std::plus<typename Container::value_type>());
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
typename Container::value_type product(Container const& cont) {
|
||||
return fold1(cont, std::multiplies<typename Container::value_type>());
|
||||
}
|
||||
|
||||
template <typename OutContainer, typename InContainer, typename Function>
|
||||
void transformInto(OutContainer& outContainer, InContainer&& inContainer, Function&& function) {
|
||||
for (auto&& elem : inContainer) {
|
||||
if (std::is_rvalue_reference<InContainer&&>::value)
|
||||
outContainer.insert(outContainer.end(), function(move(elem)));
|
||||
else
|
||||
outContainer.insert(outContainer.end(), function(elem));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutContainer, typename InContainer, typename Function>
|
||||
OutContainer transform(InContainer&& container, Function&& function) {
|
||||
OutContainer res;
|
||||
transformInto(res, forward<InContainer>(container), forward<Function>(function));
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename OutputContainer, typename Function, typename Container1, typename Container2>
|
||||
OutputContainer zipWith(Function&& function, Container1 const& cont1, Container2 const& cont2) {
|
||||
auto it1 = cont1.begin();
|
||||
auto it2 = cont2.begin();
|
||||
|
||||
OutputContainer out;
|
||||
while (it1 != cont1.end() && it2 != cont2.end()) {
|
||||
out.insert(out.end(), function(*it1, *it2));
|
||||
++it1;
|
||||
++it2;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Moves the given value and into an rvalue. Works whether or not the type has
|
||||
// a valid move constructor or not. Always leaves the given value in its
|
||||
// default constructed state.
|
||||
template <typename T>
|
||||
T take(T& t) {
|
||||
T t2 = move(t);
|
||||
t = T();
|
||||
return t2;
|
||||
}
|
||||
|
||||
template <typename Container1, typename Container2>
|
||||
bool containersEqual(Container1 const& cont1, Container2 const& cont2) {
|
||||
if (cont1.size() != cont2.size())
|
||||
return false;
|
||||
else
|
||||
return std::equal(cont1.begin(), cont1.end(), cont2.begin());
|
||||
}
|
||||
|
||||
// Wraps a unary function to produce an output iterator
|
||||
template <typename UnaryFunction>
|
||||
class FunctionOutputIterator {
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
class OutputProxy {
|
||||
public:
|
||||
OutputProxy(UnaryFunction& f)
|
||||
: m_function(f) {}
|
||||
|
||||
template <typename T>
|
||||
OutputProxy& operator=(T&& value) {
|
||||
m_function(forward<T>(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
UnaryFunction& m_function;
|
||||
};
|
||||
|
||||
explicit FunctionOutputIterator(UnaryFunction f = UnaryFunction())
|
||||
: m_function(move(f)) {}
|
||||
|
||||
OutputProxy operator*() {
|
||||
return OutputProxy(m_function);
|
||||
}
|
||||
|
||||
FunctionOutputIterator& operator++() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
FunctionOutputIterator operator++(int) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
UnaryFunction m_function;
|
||||
};
|
||||
|
||||
template <typename UnaryFunction>
|
||||
FunctionOutputIterator<UnaryFunction> makeFunctionOutputIterator(UnaryFunction f) {
|
||||
return FunctionOutputIterator<UnaryFunction>(move(f));
|
||||
}
|
||||
|
||||
// Wraps a nullary function to produce an input iterator
|
||||
template <typename NullaryFunction>
|
||||
class FunctionInputIterator {
|
||||
public:
|
||||
typedef std::output_iterator_tag iterator_category;
|
||||
typedef void value_type;
|
||||
typedef void difference_type;
|
||||
typedef void pointer;
|
||||
typedef void reference;
|
||||
|
||||
typedef typename std::result_of<NullaryFunction()>::type FunctionReturnType;
|
||||
|
||||
explicit FunctionInputIterator(NullaryFunction f = {})
|
||||
: m_function(move(f)) {}
|
||||
|
||||
FunctionReturnType operator*() {
|
||||
return m_function();
|
||||
}
|
||||
|
||||
FunctionInputIterator& operator++() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
FunctionInputIterator operator++(int) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
NullaryFunction m_function;
|
||||
};
|
||||
|
||||
template <typename NullaryFunction>
|
||||
FunctionInputIterator<NullaryFunction> makeFunctionInputIterator(NullaryFunction f) {
|
||||
return FunctionInputIterator<NullaryFunction>(move(f));
|
||||
}
|
||||
|
||||
template <typename Iterable>
|
||||
struct ReverseWrapper {
|
||||
private:
|
||||
Iterable& m_iterable;
|
||||
|
||||
public:
|
||||
ReverseWrapper(Iterable& iterable) : m_iterable(iterable) {}
|
||||
|
||||
decltype(auto) begin() const {
|
||||
return std::rbegin(m_iterable);
|
||||
}
|
||||
|
||||
decltype(auto) end() const {
|
||||
return std::rend(m_iterable);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterable>
|
||||
ReverseWrapper<Iterable> reverseIterate(Iterable& list) {
|
||||
return ReverseWrapper<Iterable>(list);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
class FinallyGuard {
|
||||
public:
|
||||
FinallyGuard(Functor functor) : functor(move(functor)), dismiss(false) {}
|
||||
|
||||
FinallyGuard(FinallyGuard&& o) : functor(move(o.functor)), dismiss(o.dismiss) {
|
||||
o.cancel();
|
||||
}
|
||||
|
||||
FinallyGuard& operator=(FinallyGuard&& o) {
|
||||
functor = move(o.functor);
|
||||
dismiss = o.dismiss;
|
||||
o.cancel();
|
||||
return *this;
|
||||
}
|
||||
|
||||
~FinallyGuard() {
|
||||
if (!dismiss)
|
||||
functor();
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
dismiss = true;
|
||||
}
|
||||
|
||||
private:
|
||||
Functor functor;
|
||||
bool dismiss;
|
||||
};
|
||||
|
||||
template <typename Functor>
|
||||
FinallyGuard<typename std::decay<Functor>::type> finally(Functor&& f) {
|
||||
return FinallyGuard<Functor>(forward<Functor>(f));
|
||||
}
|
||||
|
||||
// Generates compile time sequences of indexes from MinIndex to MaxIndex
|
||||
|
||||
template <size_t...>
|
||||
struct IndexSequence {};
|
||||
|
||||
template <size_t Min, size_t N, size_t... S>
|
||||
struct GenIndexSequence : GenIndexSequence<Min, N - 1, N - 1, S...> {};
|
||||
|
||||
template <size_t Min, size_t... S>
|
||||
struct GenIndexSequence<Min, Min, S...> {
|
||||
typedef IndexSequence<S...> type;
|
||||
};
|
||||
|
||||
// Apply a tuple as individual arguments to a function
|
||||
|
||||
template <typename Function, typename Tuple, size_t... Indexes>
|
||||
decltype(auto) tupleUnpackFunctionIndexes(Function&& function, Tuple&& args, IndexSequence<Indexes...> const&) {
|
||||
return function(get<Indexes>(forward<Tuple>(args))...);
|
||||
}
|
||||
|
||||
template <typename Function, typename Tuple>
|
||||
decltype(auto) tupleUnpackFunction(Function&& function, Tuple&& args) {
|
||||
return tupleUnpackFunctionIndexes<Function, Tuple>(forward<Function>(function), forward<Tuple>(args),
|
||||
typename GenIndexSequence<0, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
|
||||
}
|
||||
|
||||
// Apply a function to every element of a tuple. This will NOT happen in a
|
||||
// predictable order!
|
||||
|
||||
template <typename Function, typename Tuple, size_t... Indexes>
|
||||
decltype(auto) tupleApplyFunctionIndexes(Function&& function, Tuple&& args, IndexSequence<Indexes...> const&) {
|
||||
return make_tuple(function(get<Indexes>(forward<Tuple>(args)))...);
|
||||
}
|
||||
|
||||
template <typename Function, typename Tuple>
|
||||
decltype(auto) tupleApplyFunction(Function&& function, Tuple&& args) {
|
||||
return tupleApplyFunctionIndexes<Function, Tuple>(forward<Function>(function), forward<Tuple>(args),
|
||||
typename GenIndexSequence<0, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
|
||||
}
|
||||
|
||||
// Use this version if you do not care about the return value of the function
|
||||
// or your function returns void. This version DOES happen in a predictable
|
||||
// order, first argument first, last argument last.
|
||||
|
||||
template <typename Function, typename Tuple>
|
||||
void tupleCallFunctionCaller(Function&&, Tuple&&) {}
|
||||
|
||||
template <typename Tuple, typename Function, typename First, typename... Rest>
|
||||
void tupleCallFunctionCaller(Tuple&& t, Function&& function) {
|
||||
tupleCallFunctionCaller<Tuple, Function, Rest...>(forward<Tuple>(t), forward<Function>(function));
|
||||
function(get<sizeof...(Rest)>(forward<Tuple>(t)));
|
||||
}
|
||||
|
||||
template <typename Tuple, typename Function, typename... T>
|
||||
void tupleCallFunctionExpander(Tuple&& t, Function&& function, tuple<T...> const&) {
|
||||
tupleCallFunctionCaller<Tuple, Function, T...>(forward<Tuple>(t), forward<Function>(function));
|
||||
}
|
||||
|
||||
template <typename Tuple, typename Function>
|
||||
void tupleCallFunction(Tuple&& t, Function&& function) {
|
||||
tupleCallFunctionExpander<Tuple, Function>(forward<Tuple>(t), forward<Function>(function), forward<Tuple>(t));
|
||||
}
|
||||
|
||||
// Get a subset of a tuple
|
||||
|
||||
template <typename Tuple, size_t... Indexes>
|
||||
decltype(auto) subTupleIndexes(Tuple&& t, IndexSequence<Indexes...> const&) {
|
||||
return make_tuple(get<Indexes>(forward<Tuple>(t))...);
|
||||
}
|
||||
|
||||
template <size_t Min, size_t Size, typename Tuple>
|
||||
decltype(auto) subTuple(Tuple&& t) {
|
||||
return subTupleIndexes(forward<Tuple>(t), GenIndexSequence<Min, Size>::type());
|
||||
}
|
||||
|
||||
template <size_t Trim, typename Tuple>
|
||||
decltype(auto) trimTuple(Tuple&& t) {
|
||||
return subTupleIndexes(forward<Tuple>(t), typename GenIndexSequence<Trim, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
|
||||
}
|
||||
|
||||
// Unpack a parameter expansion into a container
|
||||
|
||||
template <typename Container>
|
||||
void unpackVariadicImpl(Container&) {}
|
||||
|
||||
template <typename Container, typename TFirst, typename... TRest>
|
||||
void unpackVariadicImpl(Container& container, TFirst&& tfirst, TRest&&... trest) {
|
||||
container.insert(container.end(), forward<TFirst>(tfirst));
|
||||
unpackVariadicImpl(container, forward<TRest>(trest)...);
|
||||
}
|
||||
|
||||
template <typename Container, typename... T>
|
||||
Container unpackVariadic(T&&... t) {
|
||||
Container c;
|
||||
unpackVariadicImpl(c, forward<T>(t)...);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Call a function on each entry in a variadic parameter set
|
||||
|
||||
template <typename Function>
|
||||
void callFunctionVariadic(Function&&) {}
|
||||
|
||||
template <typename Function, typename Arg1, typename... ArgRest>
|
||||
void callFunctionVariadic(Function&& function, Arg1&& arg1, ArgRest&&... argRest) {
|
||||
function(arg1);
|
||||
callFunctionVariadic(forward<Function>(function), forward<ArgRest>(argRest)...);
|
||||
}
|
||||
|
||||
template <typename... Rest>
|
||||
struct VariadicTypedef;
|
||||
|
||||
template <>
|
||||
struct VariadicTypedef<> {};
|
||||
|
||||
template <typename FirstT, typename... RestT>
|
||||
struct VariadicTypedef<FirstT, RestT...> {
|
||||
typedef FirstT First;
|
||||
typedef VariadicTypedef<RestT...> Rest;
|
||||
};
|
||||
|
||||
// For generic types, directly use the result of the signature of its
|
||||
// 'operator()'
|
||||
template <typename T>
|
||||
struct FunctionTraits : public FunctionTraits<decltype(&T::operator())> {};
|
||||
|
||||
template <typename ReturnType, typename... ArgsTypes>
|
||||
struct FunctionTraits<ReturnType(ArgsTypes...)> {
|
||||
// arity is the number of arguments.
|
||||
static constexpr size_t Arity = sizeof...(ArgsTypes);
|
||||
|
||||
typedef ReturnType Return;
|
||||
|
||||
typedef VariadicTypedef<ArgsTypes...> Args;
|
||||
typedef tuple<ArgsTypes...> ArgTuple;
|
||||
|
||||
template <size_t i>
|
||||
struct Arg {
|
||||
// the i-th argument is equivalent to the i-th tuple element of a tuple
|
||||
// composed of those arguments.
|
||||
typedef typename tuple_element<i, ArgTuple>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename... Args>
|
||||
struct FunctionTraits<ReturnType (*)(Args...)> : public FunctionTraits<ReturnType(Args...)> {};
|
||||
|
||||
template <typename FunctionType>
|
||||
struct FunctionTraits<std::function<FunctionType>> : public FunctionTraits<FunctionType> {};
|
||||
|
||||
template <typename ClassType, typename ReturnType, typename... Args>
|
||||
struct FunctionTraits<ReturnType (ClassType::*)(Args...)> : public FunctionTraits<ReturnType(Args...)> {
|
||||
typedef ClassType& OwnerType;
|
||||
};
|
||||
|
||||
template <typename ClassType, typename ReturnType, typename... Args>
|
||||
struct FunctionTraits<ReturnType (ClassType::*)(Args...) const> : public FunctionTraits<ReturnType(Args...)> {
|
||||
typedef const ClassType& OwnerType;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FunctionTraits<T&> : public FunctionTraits<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct FunctionTraits<T const&> : public FunctionTraits<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct FunctionTraits<T&&> : public FunctionTraits<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct FunctionTraits<T const&&> : public FunctionTraits<T> {};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue