diff options
author | sskvor <sskvor@yandex-team.com> | 2022-08-24 11:41:27 +0300 |
---|---|---|
committer | sskvor <sskvor@yandex-team.com> | 2022-08-24 11:41:27 +0300 |
commit | 30a75ad702329a4178784acc5bad610931c32382 (patch) | |
tree | d490edde5fe1700104ceecbcc8d443a33eb6168c /util/generic | |
parent | 26dcb3705729c807903c7c1d5757cb950e703c1a (diff) | |
download | ydb-30a75ad702329a4178784acc5bad610931c32382.tar.gz |
[util] Add specializations for const / ref qualified member functions
Diffstat (limited to 'util/generic')
-rw-r--r-- | util/generic/function.h | 35 | ||||
-rw-r--r-- | util/generic/function_ut.cpp | 69 |
2 files changed, 94 insertions, 10 deletions
diff --git a/util/generic/function.h b/util/generic/function.h index 62fa84e0cb..859cc3f849 100644 --- a/util/generic/function.h +++ b/util/generic/function.h @@ -11,15 +11,23 @@ namespace NPrivate { using TSignature = F; }; - template <typename C, typename R, typename... Args> - struct TRemoveClassImpl<R (C::*)(Args...)> { - typedef R TSignature(Args...); +#define Y_EMPTY_REF_QUALIFIER +#define Y_FOR_EACH_REF_QUALIFIERS_COMBINATION(XX) \ + XX(Y_EMPTY_REF_QUALIFIER) \ + XX(&) \ + XX(&&) \ + XX(const) \ + XX(const&) \ + XX(const&&) + +#define Y_DECLARE_REMOVE_CLASS_IMPL(qualifiers) \ + template <typename C, typename R, typename... Args> \ + struct TRemoveClassImpl<R (C::*)(Args...) qualifiers> { \ + typedef R TSignature(Args...); \ }; - template <typename C, typename R, typename... Args> - struct TRemoveClassImpl<R (C::*)(Args...) const> { - typedef R TSignature(Args...); - }; + Y_FOR_EACH_REF_QUALIFIERS_COMBINATION(Y_DECLARE_REMOVE_CLASS_IMPL) +#undef Y_DECLARE_REMOVE_CLASS_IMPL template <class T> struct TRemoveNoExceptImpl { @@ -31,11 +39,18 @@ namespace NPrivate { using Type = R(Args...); }; - template <typename R, typename C, typename... Args> - struct TRemoveNoExceptImpl<R (C::*)(Args...) noexcept> { - using Type = R (C::*)(Args...); +#define Y_DECLARE_REMOVE_NOEXCEPT_IMPL(qualifiers) \ + template <typename R, typename C, typename... Args> \ + struct TRemoveNoExceptImpl<R (C::*)(Args...) qualifiers noexcept> { \ + using Type = R (C::*)(Args...); \ }; + Y_FOR_EACH_REF_QUALIFIERS_COMBINATION(Y_DECLARE_REMOVE_NOEXCEPT_IMPL) +#undef Y_DECLARE_REMOVE_NOEXCEPT_IMPL + +#undef Y_FOR_EACH_REF_QUALIFIERS_COMBINATION +#undef Y_EMPTY_REF_QUALIFIER + template <class T> using TRemoveNoExcept = typename TRemoveNoExceptImpl<T>::Type; diff --git a/util/generic/function_ut.cpp b/util/generic/function_ut.cpp index 3880295a9f..f46188aa2a 100644 --- a/util/generic/function_ut.cpp +++ b/util/generic/function_ut.cpp @@ -8,22 +8,70 @@ Y_UNIT_TEST_SUITE(TestFunctionSignature) { return (int)x; } + int FFN(double x) noexcept { + return (int)x; + } + int FFF(double x, char xx) { return (int)x + (int)xx; } + int FFFN(double x, char xx) noexcept { + return (int)x + (int)xx; + } + struct A { int F(double x) { return FF(x); } + + int FN(double x) noexcept { + return FFN(x); + } + + int FC(double x) const { + return FF(x); + } + + int FCN(double x) const noexcept { + return FFN(x); + } + +#define Y_FOR_EACH_REF_QUALIFIED_MEMBERS(XX) \ + XX(AsMutLvalue, &, false) \ + XX(AsMutLvalueN, &, true) \ + XX(AsMutRvalue, &&, false) \ + XX(AsMutRvalueN, &&, true) \ + XX(AsConstLvalue, const&, false) \ + XX(AsConstLvalueN, const&, true) \ + XX(AsConstRvalue, const&&, false) \ + XX(AsConstRvalueN, const&&, true) + +#define Y_ADD_MEMBER(name, qualifiers, isNoexcept) \ + int name(double x) qualifiers noexcept(isNoexcept) { \ + return FF(x); \ + } + + Y_FOR_EACH_REF_QUALIFIED_MEMBERS(Y_ADD_MEMBER) +#undef Y_ADD_MEMBER }; Y_UNIT_TEST(TestPlainFunc) { UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(FF)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(FFN)>, decltype(FF)); } Y_UNIT_TEST(TestMethod) { UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(&A::F)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(&A::FN)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(&A::FC)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(&A::FCN)>, decltype(FF)); + +#define Y_CHECK_MEMBER(name, qualifiers, isNoexcept) \ + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(&A::name)>, decltype(FF)); + + Y_FOR_EACH_REF_QUALIFIED_MEMBERS(Y_CHECK_MEMBER) +#undef Y_CHECK_MEMBER } Y_UNIT_TEST(TestLambda) { @@ -31,7 +79,17 @@ Y_UNIT_TEST_SUITE(TestFunctionSignature) { return FF(x); }; + auto fn = [](double x) mutable noexcept -> int { + return FFN(x); + }; + + auto fcn = [](double x) noexcept -> int { + return FFN(x); + }; + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(f)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(fn)>, decltype(FF)); + UNIT_ASSERT_TYPES_EQUAL(TFunctionSignature<decltype(fcn)>, decltype(FF)); } Y_UNIT_TEST(TestFunction) { @@ -57,6 +115,7 @@ Y_UNIT_TEST_SUITE(TestFunctionSignature) { Y_UNIT_TEST(TestPlainFunctionTraits) { TestCT<decltype(FFF)>(); + TestCT<decltype(FFFN)>(); } Y_UNIT_TEST(TestLambdaTraits) { @@ -64,6 +123,16 @@ Y_UNIT_TEST_SUITE(TestFunctionSignature) { return FFF(xx, xxx); }; + auto fffn = [](double xx, char xxx) mutable noexcept -> int { + return FFFN(xx, xxx); + }; + + auto fffcn = [](double xx, char xxx) noexcept -> int { + return FFFN(xx, xxx); + }; + TestCT<decltype(fff)>(); + TestCT<decltype(fffn)>(); + TestCT<decltype(fffcn)>(); } } |