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

Function traits have been moved to a separate header file #1249

Merged
merged 2 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions dev/ast_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,13 +479,13 @@ namespace sqlite_orm {
}
};

template<class F, class... Args>
struct ast_iterator<function_call<F, Args...>, void> {
using node_type = function_call<F, Args...>;
template<class F, class... CallArgs>
struct ast_iterator<function_call<F, CallArgs...>, void> {
using node_type = function_call<F, CallArgs...>;

template<class L>
void operator()(const node_type& f, L& lambda) const {
iterate_ast(f.args, lambda);
iterate_ast(f.callArgs, lambda);
}
};

Expand Down
44 changes: 14 additions & 30 deletions dev/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "functional/cxx_universal.h"
#include "functional/cxx_type_traits_polyfill.h"
#include "functional/function_traits.h"
#include "tags.h"

namespace sqlite_orm {
Expand Down Expand Up @@ -44,47 +45,30 @@ namespace sqlite_orm {
std::enable_if_t<std::is_member_function_pointer<aggregate_fin_function_t<F>>::value>>> =
true;

template<class T>
struct member_function_arguments;

template<class O, class R, class... Args>
struct member_function_arguments<R (O::*)(Args...) const> {
using member_function_type = R (O::*)(Args...) const;
using tuple_type = std::tuple<std::decay_t<Args>...>;
using return_type = R;
};

template<class O, class R, class... Args>
struct member_function_arguments<R (O::*)(Args...)> {
using member_function_type = R (O::*)(Args...);
using tuple_type = std::tuple<std::decay_t<Args>...>;
using return_type = R;
};

template<class F, class SFINAE = void>
struct callable_arguments_impl;

template<class F>
struct callable_arguments_impl<F, std::enable_if_t<is_scalar_udf_v<F>>> {
using args_tuple = typename member_function_arguments<scalar_call_function_t<F>>::tuple_type;
using return_type = typename member_function_arguments<scalar_call_function_t<F>>::return_type;
using args_tuple = function_arguments<scalar_call_function_t<F>, std::tuple, std::decay_t>;
using return_type = function_return_type_t<scalar_call_function_t<F>>;
};

template<class F>
struct callable_arguments_impl<F, std::enable_if_t<is_aggregate_udf_v<F>>> {
using args_tuple = typename member_function_arguments<aggregate_step_function_t<F>>::tuple_type;
using return_type = typename member_function_arguments<aggregate_fin_function_t<F>>::return_type;
using args_tuple = function_arguments<aggregate_step_function_t<F>, std::tuple, std::decay_t>;
using return_type = function_return_type_t<aggregate_fin_function_t<F>>;
};

template<class F>
struct callable_arguments : callable_arguments_impl<F> {};

template<class UDF, class... Args>
template<class UDF, class... CallArgs>
struct function_call {
using udf_type = UDF;
using args_tuple = std::tuple<Args...>;
using args_tuple = std::tuple<CallArgs...>;

args_tuple args;
args_tuple callArgs;
};

template<class T>
Expand All @@ -95,8 +79,8 @@ namespace sqlite_orm {
struct unpacked_arg {
using type = T;
};
template<class F, class... Args>
struct unpacked_arg<function_call<F, Args...>> {
template<class F, class... CallArgs>
struct unpacked_arg<function_call<F, CallArgs...>> {
using type = typename callable_arguments<F>::return_type;
};
template<class T>
Expand Down Expand Up @@ -185,9 +169,9 @@ namespace sqlite_orm {
*/
template<class UDF>
struct function : polyfill::type_identity<UDF> {
template<typename... Args>
function_call<UDF, Args...> operator()(Args... args) const {
using args_tuple = std::tuple<Args...>;
template<typename... CallArgs>
function_call<UDF, CallArgs...> operator()(CallArgs... callArgs) const {
using args_tuple = std::tuple<CallArgs...>;
using function_args_tuple = typename callable_arguments<UDF>::args_tuple;
constexpr size_t argsCount = std::tuple_size<args_tuple>::value;
constexpr size_t functionArgsCount = std::tuple_size<function_args_tuple>::value;
Expand All @@ -197,7 +181,7 @@ namespace sqlite_orm {
polyfill::index_constant<std::min(functionArgsCount, argsCount) - 1>{})) ||
std::is_same<function_args_tuple, std::tuple<arg_values>>::value,
"The number of arguments does not match");
return {{std::forward<Args>(args)...}};
return {{std::forward<CallArgs>(callArgs)...}};
}
};
}
Expand Down
63 changes: 63 additions & 0 deletions dev/functional/function_traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once
#include "cxx_type_traits_polyfill.h"
#include "mpl.h"

namespace sqlite_orm {
namespace internal {
template<class F>
struct function_traits;

/*
* A function's return type
*/
template<class F>
using function_return_type_t = typename function_traits<F>::return_type;

/*
* A function's arguments tuple
*/
template<class F,
template<class...>
class Tuple,
template<class...> class ProjectOp = polyfill::type_identity_t>
using function_arguments = typename function_traits<F>::template arguments_tuple<Tuple, ProjectOp>;

/*
* Define nested typenames:
* - return_type
* - arguments_tuple
*/
template<class R, class... Args>
struct function_traits<R(Args...)> {
using return_type = R;

template<template<class...> class Tuple, template<class...> class ProjectOp>
using arguments_tuple = Tuple<mpl::invoke_fn_t<ProjectOp, Args>...>;
};

// non-exhaustive partial specializations of `function_traits`

template<class R, class... Args>
struct function_traits<R(Args...) const> : function_traits<R(Args...)> {};

#ifdef SQLITE_ORM_NOTHROW_ALIASES_SUPPORTED
template<class R, class... Args>
struct function_traits<R(Args...) noexcept> : function_traits<R(Args...)> {};

template<class R, class... Args>
struct function_traits<R(Args...) const noexcept> : function_traits<R(Args...)> {};
#endif

/*
* Pick signature of function pointer
*/
template<class R, class... Args>
struct function_traits<R (*)(Args...)> : function_traits<R(Args...)> {};

/*
* Pick signature of pointer-to-member function
*/
template<class F, class O>
struct function_traits<F O::*> : function_traits<F> {};
}
}
8 changes: 4 additions & 4 deletions dev/statement_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,14 @@ namespace sqlite_orm {
struct statement_serializer<built_in_aggregate_function_t<R, S, Args...>, void>
: statement_serializer<built_in_function_t<R, S, Args...>, void> {};

template<class F, class... Args>
struct statement_serializer<function_call<F, Args...>, void> {
using statement_type = function_call<F, Args...>;
template<class F, class... CallArgs>
struct statement_serializer<function_call<F, CallArgs...>, void> {
using statement_type = function_call<F, CallArgs...>;

template<class Ctx>
std::string operator()(const statement_type& statement, const Ctx& context) const {
std::stringstream ss;
ss << F::name() << "(" << streaming_expressions_tuple(statement.args, context) << ")";
ss << F::name() << "(" << streaming_expressions_tuple(statement.callArgs, context) << ")";
return ss.str();
}
};
Expand Down
1 change: 1 addition & 0 deletions dev/storage_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ namespace sqlite_orm {
auto result = polyfill::apply(udf, std::move(argsTuple));
statement_binder<return_type>().result(context, result);
},
/* finalCall = */
nullptr,
allocate_udf_storage<F>());

Expand Down
Loading