functionTraits: Add reusable "functionTakesArgument" type

Instead of doing the dispatch "function has enough arguments" +
"argument is of correct type" for runAsync specifically, extract a
reusable functionTakesArgument<Function, unsigned index, Type>, which is
either of type std::true_type or std::false_type.

Change-Id: Iecfa867a0230d29fd96ae500423a5bdd1d475106
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Eike Ziller
2016-02-25 10:08:07 +01:00
parent 62c6a07445
commit c68d270b0c
2 changed files with 52 additions and 19 deletions

View File

@@ -29,6 +29,26 @@
namespace Utils {
/*
struct functionTraits<Function>
{
using ResultType; // Return type of Function
struct argument<unsigned index>
{
using type; // type of Function argument at index (starting with 0)
}
}
struct functionTakesArgument<Function, unsigned index, ArgumentType>;
Is derived from std::true_type if Function takes an argument of type ArgumentType at index.
Otherwise derived from std::false_type.
*/
////////////////////
// functionTraits
////////////////////
// for callables. defined below.
template <typename Callable>
struct functionTraits;
@@ -135,4 +155,34 @@ struct functionTraits<Callable&&> : public functionTraits<Callable>
{
};
////////////////////
// functionTakesArgument
////////////////////
namespace Internal {
template <typename HasArity/*true_type or false_type*/,
typename Function, unsigned index, typename T>
struct functionTakesArgumentArityDispatch;
template <typename Function, unsigned index, typename T>
struct functionTakesArgumentArityDispatch<std::false_type, Function, index, T>
: public std::false_type
{
};
template <typename Function, unsigned index, typename T>
struct functionTakesArgumentArityDispatch<std::true_type, Function, index, T>
: public std::is_same<T, typename functionTraits<Function>::template argument<index>::type>
{
};
} // Internal
template <typename Function, unsigned index, typename T>
struct functionTakesArgument : public Internal::functionTakesArgumentArityDispatch<
std::integral_constant<bool, (functionTraits<Function>::arity > index)>,
Function, index, T>
{
};
} // Utils

View File

@@ -260,23 +260,6 @@ void runAsyncQFutureInterfaceDispatch(std::false_type, QFutureInterface<ResultTy
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...);
}
// function that takes at least one argument which could be QFutureInterface
template <typename ResultType, typename Function, typename... Args>
void runAsyncArityDispatch(std::true_type, QFutureInterface<ResultType> futureInterface, Function &&function, Args&&... args)
{
runAsyncQFutureInterfaceDispatch(std::is_same<QFutureInterface<ResultType>&,
typename functionTraits<Function>::template argument<0>::type>(),
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...);
}
// function that does not take an argument, so it does not take a QFutureInterface
template <typename ResultType, typename Function, typename... Args>
void runAsyncArityDispatch(std::false_type, QFutureInterface<ResultType> futureInterface, Function &&function, Args&&... args)
{
runAsyncQFutureInterfaceDispatch(std::false_type(),
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...);
}
// function, function pointer, or other callable object that is no member pointer
template <typename ResultType, typename Function, typename... Args,
typename = typename std::enable_if<
@@ -284,8 +267,8 @@ template <typename ResultType, typename Function, typename... Args,
>::type>
void runAsyncMemberDispatch(QFutureInterface<ResultType> futureInterface, Function &&function, Args&&... args)
{
runAsyncArityDispatch(std::integral_constant<bool, (functionTraits<Function>::arity > 0)>(),
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...);
runAsyncQFutureInterfaceDispatch(functionTakesArgument<Function, 0, QFutureInterface<ResultType>&>(),
futureInterface, std::forward<Function>(function), std::forward<Args>(args)...);
}
// Function = member function