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/intrinsic_validation_test.cc
|
||||||
resolver/is_host_shareable_test.cc
|
resolver/is_host_shareable_test.cc
|
||||||
resolver/is_storeable_test.cc
|
resolver/is_storeable_test.cc
|
||||||
|
resolver/pipeline_overridable_constant_test.cc
|
||||||
resolver/ptr_ref_test.cc
|
resolver/ptr_ref_test.cc
|
||||||
resolver/ptr_ref_validation_test.cc
|
resolver/ptr_ref_validation_test.cc
|
||||||
resolver/resolver_constants_test.cc
|
resolver/resolver_constants_test.cc
|
||||||
resolver/pipeline_overridable_constant_test.cc
|
|
||||||
resolver/resolver_test_helper.cc
|
resolver/resolver_test_helper.cc
|
||||||
resolver/resolver_test_helper.h
|
resolver/resolver_test_helper.h
|
||||||
resolver/resolver_test.cc
|
resolver/resolver_test.cc
|
||||||
|
@ -693,11 +693,6 @@ if(${TINT_BUILD_TESTS})
|
||||||
resolver/var_let_test.cc
|
resolver/var_let_test.cc
|
||||||
resolver/var_let_validation_test.cc
|
resolver/var_let_validation_test.cc
|
||||||
scope_stack_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/atomic_type_test.cc
|
||||||
sem/bool_type_test.cc
|
sem/bool_type_test.cc
|
||||||
sem/depth_multisampled_texture_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/external_texture_type_test.cc
|
||||||
sem/f32_type_test.cc
|
sem/f32_type_test.cc
|
||||||
sem/i32_type_test.cc
|
sem/i32_type_test.cc
|
||||||
|
sem/intrinsic_test.cc
|
||||||
sem/matrix_type_test.cc
|
sem/matrix_type_test.cc
|
||||||
sem/multisampled_texture_type_test.cc
|
sem/multisampled_texture_type_test.cc
|
||||||
sem/pointer_type_test.cc
|
sem/pointer_type_test.cc
|
||||||
|
@ -718,6 +714,11 @@ if(${TINT_BUILD_TESTS})
|
||||||
sem/type_manager_test.cc
|
sem/type_manager_test.cc
|
||||||
sem/u32_type_test.cc
|
sem/u32_type_test.cc
|
||||||
sem/vector_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/defer_test.cc
|
||||||
utils/enum_set_test.cc
|
utils/enum_set_test.cc
|
||||||
utils/get_or_create_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,
|
bool TraverseExpressions(const ast::Expression* root,
|
||||||
diag::List& diags,
|
diag::List& diags,
|
||||||
CALLBACK&& callback) {
|
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};
|
std::vector<const ast::Expression*> to_visit{root};
|
||||||
|
|
||||||
auto push_pair = [&](const ast::Expression* left,
|
auto push_pair = [&](const ast::Expression* left,
|
||||||
|
|
|
@ -303,7 +303,8 @@ class Castable : public BASE {
|
||||||
/// object is of, or derives from the class `TO`.
|
/// object is of, or derives from the class `TO`.
|
||||||
template <int FLAGS = 0, typename Pred = detail::Infer>
|
template <int FLAGS = 0, typename Pred = detail::Infer>
|
||||||
inline bool Is(Pred&& pred) const {
|
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),
|
return tint::Is<TO, FLAGS>(static_cast<const CLASS*>(this),
|
||||||
std::forward<Pred>(pred));
|
std::forward<Pred>(pred));
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ class CloneContext {
|
||||||
/// F is a pointer of (or derives from) type T.
|
/// F is a pointer of (or derives from) type T.
|
||||||
template <typename F, typename T>
|
template <typename F, typename T>
|
||||||
using ParamTypeIsPtrOf = traits::IsTypeOrDerived<
|
using ParamTypeIsPtrOf = traits::IsTypeOrDerived<
|
||||||
typename std::remove_pointer<traits::ParamTypeT<F, 0>>::type,
|
typename std::remove_pointer<traits::ParameterType<F, 0>>::type,
|
||||||
T>;
|
T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -274,7 +274,7 @@ class CloneContext {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
traits::EnableIf<ParamTypeIsPtrOf<F, Cloneable>::value, CloneContext>&
|
traits::EnableIf<ParamTypeIsPtrOf<F, Cloneable>::value, CloneContext>&
|
||||||
ReplaceAll(F&& replacer) {
|
ReplaceAll(F&& replacer) {
|
||||||
using TPtr = traits::ParamTypeT<F, 0>;
|
using TPtr = traits::ParameterType<F, 0>;
|
||||||
using T = typename std::remove_pointer<TPtr>::type;
|
using T = typename std::remove_pointer<TPtr>::type;
|
||||||
for (auto& transform : transforms_) {
|
for (auto& transform : transforms_) {
|
||||||
if (transform.typeinfo->Is(TypeInfo::Of<T>()) ||
|
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>
|
template <int N, typename... Types>
|
||||||
using NthTypeOf = typename std::tuple_element<N, std::tuple<Types...>>::type;
|
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
|
/// Signature describes the signature of a function.
|
||||||
/// of the function, method, static method, lambda, or function-like object `F`.
|
template <typename RETURN, typename... PARAMETERS>
|
||||||
template <typename F, int N>
|
struct Signature {
|
||||||
struct ParamType {
|
/// The return type of the function signature
|
||||||
/// The type of the `N`th parameter of the function-like object `F`
|
using ret = RETURN;
|
||||||
using type = typename ParamType<decltype(&F::operator()), N>::type;
|
/// 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.
|
/// SignatureOf is a traits helper that infers the signature of the function,
|
||||||
template <typename R, int N, typename... Args>
|
/// method, static method, lambda, or function-like object `F`.
|
||||||
struct ParamType<R (*)(Args...), N> {
|
template <typename F>
|
||||||
/// Arg is the raw type of the `N`th parameter of the function
|
struct SignatureOf {
|
||||||
using Arg = NthTypeOf<N, Args...>;
|
/// The signature of the function-like object `F`
|
||||||
/// The type of the `N`th parameter of the function
|
using type = typename SignatureOf<decltype(&F::operator())>::type;
|
||||||
using type = Decay<Arg>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ParamType specialization for a non-static method.
|
/// SignatureOf specialization for a regular function or static method.
|
||||||
template <typename R, typename C, int N, typename... Args>
|
template <typename R, typename... ARGS>
|
||||||
struct ParamType<R (C::*)(Args...), N> {
|
struct SignatureOf<R (*)(ARGS...)> {
|
||||||
/// Arg is the raw type of the `N`th parameter of the function
|
/// The signature of the function-like object `F`
|
||||||
using Arg = NthTypeOf<N, Args...>;
|
using type = Signature<typename std::decay<R>::type,
|
||||||
/// The type of the `N`th parameter of the function
|
typename std::decay<ARGS>::type...>;
|
||||||
using type = Decay<Arg>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ParamType specialization for a non-static, const method.
|
/// SignatureOf specialization for a non-static method.
|
||||||
template <typename R, typename C, int N, typename... Args>
|
template <typename R, typename C, typename... ARGS>
|
||||||
struct ParamType<R (C::*)(Args...) const, N> {
|
struct SignatureOf<R (C::*)(ARGS...)> {
|
||||||
/// Arg is the raw type of the `N`th parameter of the function
|
/// The signature of the function-like object `F`
|
||||||
using Arg = NthTypeOf<N, Args...>;
|
using type = Signature<typename std::decay<R>::type,
|
||||||
/// The type of the `N`th parameter of the function
|
typename std::decay<ARGS>::type...>;
|
||||||
using type = Decay<Arg>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ParamTypeT is an alias to `typename ParamType<F, N>::type`.
|
/// SignatureOf specialization for a non-static, const method.
|
||||||
template <typename F, int N>
|
template <typename R, typename C, typename... ARGS>
|
||||||
using ParamTypeT = typename ParamType<F, N>::type;
|
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
|
/// `IsTypeOrDerived<T, BASE>::value` is true iff `T` is of type `BASE`, or
|
||||||
/// derives from `BASE`.
|
/// derives from `BASE`.
|
||||||
|
|
|
@ -28,10 +28,15 @@ void F3(int, S, float) {}
|
||||||
TEST(ParamType, Function) {
|
TEST(ParamType, Function) {
|
||||||
F1({}); // Avoid unused method warning
|
F1({}); // Avoid unused method warning
|
||||||
F3(0, {}, 0); // 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<ParameterType<decltype(&F1), 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<decltype(&F3), 0>, int>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 1>, S>::value, "");
|
static_assert(std::is_same<ParameterType<decltype(&F3), 1>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&F3), 2>, float>::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) {
|
TEST(ParamType, Method) {
|
||||||
|
@ -42,11 +47,16 @@ TEST(ParamType, Method) {
|
||||||
};
|
};
|
||||||
C().F1({}); // Avoid unused method warning
|
C().F1({}); // Avoid unused method warning
|
||||||
C().F3(0, {}, 0); // 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<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<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::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) {
|
TEST(ParamType, ConstMethod) {
|
||||||
|
@ -57,11 +67,16 @@ TEST(ParamType, ConstMethod) {
|
||||||
};
|
};
|
||||||
C().F1({}); // Avoid unused method warning
|
C().F1({}); // Avoid unused method warning
|
||||||
C().F3(0, {}, 0); // 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<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<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::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) {
|
TEST(ParamType, StaticMethod) {
|
||||||
|
@ -72,29 +87,42 @@ TEST(ParamType, StaticMethod) {
|
||||||
};
|
};
|
||||||
C::F1({}); // Avoid unused method warning
|
C::F1({}); // Avoid unused method warning
|
||||||
C::F3(0, {}, 0); // 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<ParameterType<decltype(&C::F1), 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(&C::F3), 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<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::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) {
|
TEST(ParamType, FunctionLike) {
|
||||||
using F1 = std::function<void(S)>;
|
using F1 = std::function<void(S)>;
|
||||||
using F3 = std::function<void(int, S, float)>;
|
using F3 = std::function<void(int, S, float)>;
|
||||||
static_assert(std::is_same<ParamTypeT<F1, 0>, S>::value, "");
|
static_assert(std::is_same<ParameterType<F1, 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<F3, 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<F3, 0>, int>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<F3, 1>, S>::value, "");
|
static_assert(std::is_same<ParameterType<F3, 1>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<F3, 2>, float>::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) {
|
TEST(ParamType, Lambda) {
|
||||||
auto l1 = [](S) {};
|
auto l1 = [](S) {};
|
||||||
auto l3 = [](int, S, float) {};
|
auto l3 = [](int, S, float) {};
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(l1), 0>, S>::value, "");
|
static_assert(std::is_same<ParameterType<decltype(l1), 0>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 0>, int>::value, "");
|
static_assert(std::is_same<ParameterType<decltype(l3), 0>, int>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 1>, S>::value, "");
|
static_assert(std::is_same<ParameterType<decltype(l3), 1>, S>::value, "");
|
||||||
static_assert(std::is_same<ParamTypeT<decltype(l3), 2>, float>::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
|
} // namespace traits
|
||||||
|
|
Loading…
Reference in New Issue