traits: Add SignatureOf helper
This a more powerful version of the ParamType class. It provide all the same information as before, plus function return type and number of parameters. Change-Id: If03feed0c1b94434fa95340b6b6277621b4f81b4 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/69100 Auto-Submit: Ben Clayton <bclayton@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
5c9a80b6f6
commit
1a8171c08b
|
@ -675,10 +675,10 @@ if(${TINT_BUILD_TESTS})
|
|||
resolver/intrinsic_validation_test.cc
|
||||
resolver/is_host_shareable_test.cc
|
||||
resolver/is_storeable_test.cc
|
||||
resolver/pipeline_overridable_constant_test.cc
|
||||
resolver/ptr_ref_test.cc
|
||||
resolver/ptr_ref_validation_test.cc
|
||||
resolver/resolver_constants_test.cc
|
||||
resolver/pipeline_overridable_constant_test.cc
|
||||
resolver/resolver_test_helper.cc
|
||||
resolver/resolver_test_helper.h
|
||||
resolver/resolver_test.cc
|
||||
|
@ -693,11 +693,6 @@ if(${TINT_BUILD_TESTS})
|
|||
resolver/var_let_test.cc
|
||||
resolver/var_let_validation_test.cc
|
||||
scope_stack_test.cc
|
||||
sem/intrinsic_test.cc
|
||||
symbol_table_test.cc
|
||||
symbol_test.cc
|
||||
transform/transform_test.cc
|
||||
test_main.cc
|
||||
sem/atomic_type_test.cc
|
||||
sem/bool_type_test.cc
|
||||
sem/depth_multisampled_texture_type_test.cc
|
||||
|
@ -705,6 +700,7 @@ if(${TINT_BUILD_TESTS})
|
|||
sem/external_texture_type_test.cc
|
||||
sem/f32_type_test.cc
|
||||
sem/i32_type_test.cc
|
||||
sem/intrinsic_test.cc
|
||||
sem/matrix_type_test.cc
|
||||
sem/multisampled_texture_type_test.cc
|
||||
sem/pointer_type_test.cc
|
||||
|
@ -718,6 +714,11 @@ if(${TINT_BUILD_TESTS})
|
|||
sem/type_manager_test.cc
|
||||
sem/u32_type_test.cc
|
||||
sem/vector_type_test.cc
|
||||
symbol_table_test.cc
|
||||
symbol_test.cc
|
||||
test_main.cc
|
||||
traits_test.cc
|
||||
transform/transform_test.cc
|
||||
utils/defer_test.cc
|
||||
utils/enum_set_test.cc
|
||||
utils/get_or_create_test.cc
|
||||
|
|
|
@ -62,7 +62,7 @@ template <TraverseOrder ORDER = TraverseOrder::LeftToRight, typename CALLBACK>
|
|||
bool TraverseExpressions(const ast::Expression* root,
|
||||
diag::List& diags,
|
||||
CALLBACK&& callback) {
|
||||
using EXPR_TYPE = std::remove_pointer_t<traits::ParamTypeT<CALLBACK, 0>>;
|
||||
using EXPR_TYPE = std::remove_pointer_t<traits::ParameterType<CALLBACK, 0>>;
|
||||
std::vector<const ast::Expression*> to_visit{root};
|
||||
|
||||
auto push_pair = [&](const ast::Expression* left,
|
||||
|
|
|
@ -303,7 +303,8 @@ class Castable : public BASE {
|
|||
/// object is of, or derives from the class `TO`.
|
||||
template <int FLAGS = 0, typename Pred = detail::Infer>
|
||||
inline bool Is(Pred&& pred) const {
|
||||
using TO = typename std::remove_pointer<traits::ParamTypeT<Pred, 0>>::type;
|
||||
using TO =
|
||||
typename std::remove_pointer<traits::ParameterType<Pred, 0>>::type;
|
||||
return tint::Is<TO, FLAGS>(static_cast<const CLASS*>(this),
|
||||
std::forward<Pred>(pred));
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class CloneContext {
|
|||
/// F is a pointer of (or derives from) type T.
|
||||
template <typename F, typename T>
|
||||
using ParamTypeIsPtrOf = traits::IsTypeOrDerived<
|
||||
typename std::remove_pointer<traits::ParamTypeT<F, 0>>::type,
|
||||
typename std::remove_pointer<traits::ParameterType<F, 0>>::type,
|
||||
T>;
|
||||
|
||||
public:
|
||||
|
@ -274,7 +274,7 @@ class CloneContext {
|
|||
template <typename F>
|
||||
traits::EnableIf<ParamTypeIsPtrOf<F, Cloneable>::value, CloneContext>&
|
||||
ReplaceAll(F&& replacer) {
|
||||
using TPtr = traits::ParamTypeT<F, 0>;
|
||||
using TPtr = traits::ParameterType<F, 0>;
|
||||
using T = typename std::remove_pointer<TPtr>::type;
|
||||
for (auto& transform : transforms_) {
|
||||
if (transform.typeinfo->Is(TypeInfo::Of<T>()) ||
|
||||
|
|
79
src/traits.h
79
src/traits.h
|
@ -28,44 +28,63 @@ using Decay = typename std::decay<T>::type;
|
|||
template <int N, typename... Types>
|
||||
using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;
|
||||
|
||||
/// ParamType is a traits helper that infers the type of the `N`th parameter
|
||||
/// of the function, method, static method, lambda, or function-like object `F`.
|
||||
template <typename F, int N>
|
||||
struct ParamType {
|
||||
/// The type of the `N`th parameter of the function-like object `F`
|
||||
using type = typename ParamType<decltype(&F::operator()), N>::type;
|
||||
/// Signature describes the signature of a function.
|
||||
template <typename RETURN, typename... PARAMETERS>
|
||||
struct Signature {
|
||||
/// The return type of the function signature
|
||||
using ret = RETURN;
|
||||
/// The parameters of the function signature held in a std::tuple
|
||||
using parameters = std::tuple<PARAMETERS...>;
|
||||
/// The type of the Nth parameter of function signature
|
||||
template <std::size_t N>
|
||||
using parameter = NthTypeOf<N, PARAMETERS...>;
|
||||
/// The total number of parameters
|
||||
static constexpr std::size_t parameter_count = sizeof...(PARAMETERS);
|
||||
};
|
||||
|
||||
/// ParamType specialization for a regular function or static method.
|
||||
template <typename R, int N, typename... Args>
|
||||
struct ParamType<R (*)(Args...), N> {
|
||||
/// Arg is the raw type of the `N`th parameter of the function
|
||||
using Arg = NthTypeOf<N, Args...>;
|
||||
/// The type of the `N`th parameter of the function
|
||||
using type = Decay<Arg>;
|
||||
/// SignatureOf is a traits helper that infers the signature of the function,
|
||||
/// method, static method, lambda, or function-like object `F`.
|
||||
template <typename F>
|
||||
struct SignatureOf {
|
||||
/// The signature of the function-like object `F`
|
||||
using type = typename SignatureOf<decltype(&F::operator())>::type;
|
||||
};
|
||||
|
||||
/// ParamType specialization for a non-static method.
|
||||
template <typename R, typename C, int N, typename... Args>
|
||||
struct ParamType<R (C::*)(Args...), N> {
|
||||
/// Arg is the raw type of the `N`th parameter of the function
|
||||
using Arg = NthTypeOf<N, Args...>;
|
||||
/// The type of the `N`th parameter of the function
|
||||
using type = Decay<Arg>;
|
||||
/// SignatureOf specialization for a regular function or static method.
|
||||
template <typename R, typename... ARGS>
|
||||
struct SignatureOf<R (*)(ARGS...)> {
|
||||
/// The signature of the function-like object `F`
|
||||
using type = Signature<typename std::decay<R>::type,
|
||||
typename std::decay<ARGS>::type...>;
|
||||
};
|
||||
|
||||
/// ParamType specialization for a non-static, const method.
|
||||
template <typename R, typename C, int N, typename... Args>
|
||||
struct ParamType<R (C::*)(Args...) const, N> {
|
||||
/// Arg is the raw type of the `N`th parameter of the function
|
||||
using Arg = NthTypeOf<N, Args...>;
|
||||
/// The type of the `N`th parameter of the function
|
||||
using type = Decay<Arg>;
|
||||
/// SignatureOf specialization for a non-static method.
|
||||
template <typename R, typename C, typename... ARGS>
|
||||
struct SignatureOf<R (C::*)(ARGS...)> {
|
||||
/// The signature of the function-like object `F`
|
||||
using type = Signature<typename std::decay<R>::type,
|
||||
typename std::decay<ARGS>::type...>;
|
||||
};
|
||||
|
||||
/// ParamTypeT is an alias to `typename ParamType<F, N>::type`.
|
||||
template <typename F, int N>
|
||||
using ParamTypeT = typename ParamType<F, N>::type;
|
||||
/// SignatureOf specialization for a non-static, const method.
|
||||
template <typename R, typename C, typename... ARGS>
|
||||
struct SignatureOf<R (C::*)(ARGS...) const> {
|
||||
/// The signature of the function-like object `F`
|
||||
using type = Signature<typename std::decay<R>::type,
|
||||
typename std::decay<ARGS>::type...>;
|
||||
};
|
||||
|
||||
/// SignatureOfT is an alias to `typename SignatureOf<F>::type`.
|
||||
template <typename F>
|
||||
using SignatureOfT = typename SignatureOf<F>::type;
|
||||
|
||||
/// ParameterType is an alias to `typename SignatureOf<F>::type::parameter<N>`.
|
||||
template <typename F, std::size_t N>
|
||||
using ParameterType = typename SignatureOfT<F>::template parameter<N>;
|
||||
|
||||
/// ReturnType is an alias to `typename SignatureOf<F>::type::ret`.
|
||||
template <typename F>
|
||||
using ReturnType = typename SignatureOfT<F>::ret;
|
||||
|
||||
/// `IsTypeOrDerived<T, BASE>::value` is true iff `T` is of type `BASE`, or
|
||||
/// derives from `BASE`.
|
||||
|
|
|
@ -28,10 +28,15 @@ void F3(int, S, float) {}
|
|||
TEST(ParamType, Function) {
|
||||
F1({}); // Avoid unused method warning
|
||||
F3(0, {}, 0); // Avoid unused method warning
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 2>, float>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&F3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&F3), 2>, float>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ReturnType<decltype(&F1)>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(&F3)>, void>::value, "");
|
||||
static_assert(SignatureOfT<decltype(&F1)>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<decltype(&F3)>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
TEST(ParamType, Method) {
|
||||
|
@ -42,11 +47,16 @@ TEST(ParamType, Method) {
|
|||
};
|
||||
C().F1({}); // Avoid unused method warning
|
||||
C().F3(0, {}, 0); // Avoid unused method warning
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 2>, float>::value,
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F1)>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F3)>, void>::value, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F1)>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F3)>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
TEST(ParamType, ConstMethod) {
|
||||
|
@ -57,11 +67,16 @@ TEST(ParamType, ConstMethod) {
|
|||
};
|
||||
C().F1({}); // Avoid unused method warning
|
||||
C().F3(0, {}, 0); // Avoid unused method warning
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 2>, float>::value,
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F1)>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F3)>, void>::value, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F1)>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F3)>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
TEST(ParamType, StaticMethod) {
|
||||
|
@ -72,29 +87,42 @@ TEST(ParamType, StaticMethod) {
|
|||
};
|
||||
C::F1({}); // Avoid unused method warning
|
||||
C::F3(0, {}, 0); // Avoid unused method warning
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 2>, float>::value,
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 0>, int>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(&C::F3), 2>, float>::value,
|
||||
"");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F1)>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(&C::F3)>, void>::value, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F1)>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<decltype(&C::F3)>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
TEST(ParamType, FunctionLike) {
|
||||
using F1 = std::function<void(S)>;
|
||||
using F3 = std::function<void(int, S, float)>;
|
||||
static_assert(std::is_same<ParamTypeT<F1, 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<F3, 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<F3, 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<F3, 2>, float>::value, "");
|
||||
static_assert(std::is_same<ParameterType<F1, 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<F3, 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParameterType<F3, 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<F3, 2>, float>::value, "");
|
||||
static_assert(std::is_same<ReturnType<F1>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<F3>, void>::value, "");
|
||||
static_assert(SignatureOfT<F1>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<F3>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
TEST(ParamType, Lambda) {
|
||||
auto l1 = [](S) {};
|
||||
auto l3 = [](int, S, float) {};
|
||||
static_assert(std::is_same<ParamTypeT<decltype(l1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 2>, float>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(l1), 0>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(l3), 0>, int>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(l3), 1>, S>::value, "");
|
||||
static_assert(std::is_same<ParameterType<decltype(l3), 2>, float>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(l1)>, void>::value, "");
|
||||
static_assert(std::is_same<ReturnType<decltype(l3)>, void>::value, "");
|
||||
static_assert(SignatureOfT<decltype(l1)>::parameter_count == 1, "");
|
||||
static_assert(SignatureOfT<decltype(l3)>::parameter_count == 3, "");
|
||||
}
|
||||
|
||||
} // namespace traits
|
||||
|
|
Loading…
Reference in New Issue