From c2537c83b906219a3b1a7ad0f612e77a6e89bd54 Mon Sep 17 00:00:00 2001 From: tholenst <tholenst@google.com> Date: Tue, 9 Apr 2019 08:08:03 -0700 Subject: [PATCH] Add a template trait class HasDuplicates<...> for internal use. This is made such that HasDuplicates<...>::value is true iff the given list has a duplicate. We will use this later in the generalized key managers. PiperOrigin-RevId: 242668181 GitOrigin-RevId: 9df38ddf4bafe0396f8ba7d084729aa0e54507e6 --- cc/BUILD.bazel | 17 ++++++++ cc/CMakeLists.txt | 15 +++++++ cc/core/template_util.h | 71 ++++++++++++++++++++++++++++++++++ cc/core/template_utils_test.cc | 43 ++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 cc/core/template_util.h create mode 100644 cc/core/template_utils_test.cc diff --git a/cc/BUILD.bazel b/cc/BUILD.bazel index 193d0ed8d..4d51c49ee 100644 --- a/cc/BUILD.bazel +++ b/cc/BUILD.bazel @@ -601,6 +601,14 @@ cc_library( ], ) +cc_library( + name = "core/template_util", + include_prefix = "tink", + strip_include_prefix = "/cc", + hdrs = ["core/template_util.h"], + deps = ["@com_google_absl//absl/meta:type_traits"], +) + # Settings for building in various environments. config_setting( name = "linux_x86_64", @@ -975,3 +983,12 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "core/template_utils_test", + srcs = ["core/template_utils_test.cc"], + deps = [ + ":core/template_util", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/cc/CMakeLists.txt b/cc/CMakeLists.txt index 5e6e814fc..01c1f3da2 100644 --- a/cc/CMakeLists.txt +++ b/cc/CMakeLists.txt @@ -507,6 +507,14 @@ tink_cc_library( absl::synchronization ) +tink_cc_library( + NAME template_util + SRCS + core/template_util.h + DEPS + absl::meta +) + if (TINK_BUILD_SHARED_LIB) add_library(tink SHARED ${TINK_PUBLIC_APIS} @@ -736,3 +744,10 @@ tink_cc_test( tink::util::test_util ) +tink_cc_test( + NAME template_utils_test + SRCS core/template_utils_test.cc + DEPS + tink::core::template_utils +) + diff --git a/cc/core/template_util.h b/cc/core/template_util.h new file mode 100644 index 000000000..0c55aa036 --- /dev/null +++ b/cc/core/template_util.h @@ -0,0 +1,71 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef TINK_CORE_TEMPLATE_UTIL_H +#define TINK_CORE_TEMPLATE_UTIL_H + +#include <tuple> +#include <type_traits> + +#include "absl/meta/type_traits.h" + +namespace crypto { +namespace tink { + +namespace internal { + +// A helper class template which decides if the TestType occurs in the Tuple +// For example, OccursInTuple<int, std::tuple<float, float>>::value == false, +// and OccursInTuple<int, std::tuple<float, int>>::value == true. Not intended +// to be used directly. + +// First declare the template which always takes two parameters. +template <typename TestType, typename Tuple> +class OccursInList; + +// In the special case where the tuple is empty, the result is false. +template <typename TestType> +class OccursInList<TestType, std::tuple<>> : public std::false_type {}; + +// If the list is not empty, the result is true if TestType equals the first in +// the list, or TestType occurs in the rest of the list. +template <typename TestType, typename First, typename... List> +class OccursInList<TestType, std::tuple<First, List...>> + : public absl::disjunction< + std::is_same<TestType, First>, + OccursInList<TestType, typename std::tuple<List...>>> {}; + +// The class HasDuplicates. Defines ::value as true in case the given list has +// a duplicate, false otherwise. +template <typename... Args> +class HasDuplicates; + +// Empty list has no duplicates. +template <> +class HasDuplicates<> : public std::false_type {}; + +// Non-empty list has a duplicate if the first appears in the rest, or if the +// rest has a duplicate. +template <typename First, typename... List> +class HasDuplicates<First, List...> + : public absl::disjunction< + OccursInList<First, typename std::tuple<List...>>, + HasDuplicates<List...>> {}; + +} // namespace internal +} // namespace tink +} // namespace crypto + +#endif // TINK_CORE_TEMPLATE_UTIL_H diff --git a/cc/core/template_utils_test.cc b/cc/core/template_utils_test.cc new file mode 100644 index 000000000..8323c8a62 --- /dev/null +++ b/cc/core/template_utils_test.cc @@ -0,0 +1,43 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "tink/core/template_util.h" + +namespace crypto { +namespace tink { +namespace internal { + +class C0 {}; +class C1 {}; +class C2 {}; +class C3 {}; +class C4 {}; + +static_assert(!HasDuplicates<>::value, ""); +static_assert(!HasDuplicates<C0>::value, ""); +static_assert(!HasDuplicates<C0, C1>::value, ""); +static_assert(!HasDuplicates<C0, C1, C2>::value, ""); +static_assert(!HasDuplicates<C0, C1, C2, C3>::value, ""); + +static_assert(HasDuplicates<C0, C0>::value, ""); +static_assert(HasDuplicates<C0, C1, C0>::value, ""); +static_assert(HasDuplicates<C0, C1, C1>::value, ""); +static_assert(HasDuplicates<C0, C0, C1>::value, ""); +static_assert(HasDuplicates<C0, C1, C2, C3, C1, C4>::value, ""); + +} // namespace internal +} // namespace tink +} // namespace crypto -- GitLab