From c2e754829628d1e9b7a16b3389cfdace76950fdf Mon Sep 17 00:00:00 2001 From: misterg Date: Tue, 19 Sep 2017 16:54:40 -0400 Subject: Initial Commit --- absl/utility/BUILD.bazel | 34 +++++++++ absl/utility/utility.cc | 27 +++++++ absl/utility/utility.h | 177 +++++++++++++++++++++++++++++++++++++++++++ absl/utility/utility_test.cc | 163 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 401 insertions(+) create mode 100644 absl/utility/BUILD.bazel create mode 100644 absl/utility/utility.cc create mode 100644 absl/utility/utility.h create mode 100644 absl/utility/utility_test.cc (limited to 'absl/utility') diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel new file mode 100644 index 0000000..73d0519 --- /dev/null +++ b/absl/utility/BUILD.bazel @@ -0,0 +1,34 @@ +load( + "//absl:copts.bzl", + "ABSL_DEFAULT_COPTS", + "ABSL_TEST_COPTS", +) +load( + "//absl:test_dependencies.bzl", + "GUNIT_MAIN_DEPS_SELECTOR", +) + +package(default_visibility = ["//visibility:public"]) + +licenses(["unencumbered"]) # Owned by Google + +cc_library( + name = "utility", + srcs = ["utility.cc"], + hdrs = ["utility.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + "//absl/base:config", + "//absl/meta:type_traits", + ], +) + +cc_test( + name = "utility_test", + srcs = ["utility_test.cc"], + copts = ABSL_TEST_COPTS, + deps = [ + ":utility", + "//absl/base:core_headers", + ] + select(GUNIT_MAIN_DEPS_SELECTOR), +) diff --git a/absl/utility/utility.cc b/absl/utility/utility.cc new file mode 100644 index 0000000..fce79f5 --- /dev/null +++ b/absl/utility/utility.cc @@ -0,0 +1,27 @@ +// Copyright 2017 The Abseil Authors. +// +// 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. + +// ----------------------------------------------------------------------------- +// File: ascii.h +// ----------------------------------------------------------------------------- +// +#include "absl/utility/utility.h" + +namespace absl { + +#ifndef ABSL_HAVE_STD_OPTIONAL +const in_place_t in_place{}; +#endif + +} // namespace absl diff --git a/absl/utility/utility.h b/absl/utility/utility.h new file mode 100644 index 0000000..4f4a062 --- /dev/null +++ b/absl/utility/utility.h @@ -0,0 +1,177 @@ +// Copyright 2017 The Abseil Authors. +// +// 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. +// + +// absl/utility:utility is an extension of the header +// +// It provides stand-ins for C++14's std::integer_sequence and +// related utilities. They are intended to be exactly equivalent. +// - integer_sequence == std::integer_sequence +// - index_sequence == std::index_sequence +// - make_integer_sequence == std::make_integer_sequence +// - make_index_sequence == std::make_index_sequence +// - index_sequence_for == std::index_sequence_for +// +// It also provides the tag types in_place_t, in_place_type_t, and +// in_place_index_t, as well as the constant in_place, and constexpr std::move +// and std::forward impolementations in C++11. +// +// References: +// http://en.cppreference.com/w/cpp/utility/integer_sequence +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html +// +// Example: +// // Unpack a tuple for use as a function call's argument list. +// +// template +// auto Impl(F f, const Tup& tup, index_sequence) +// -> decltype(f(std::get(tup) ...)) { +// return f(std::get(tup) ...); +// } +// +// template +// using TupIdxSeq = make_index_sequence::value>; +// +// template +// auto ApplyFromTuple(F f, const Tup& tup) +// -> decltype(Impl(f, tup, TupIdxSeq{})) { +// return Impl(f, tup, TupIdxSeq{}); +// } +#ifndef ABSL_UTILITY_UTILITY_H_ +#define ABSL_UTILITY_UTILITY_H_ + +#include +#include +#include + +#include "absl/base/config.h" +#include "absl/meta/type_traits.h" + +namespace absl { + +// Equivalent to std::integer_sequence. +// +// Function templates can deduce compile-time integer sequences by accepting +// an argument of integer_sequence. This is a common need when +// working with C++11 variadic templates. +// +// T - the integer type of the sequence elements +// ...Ints - a parameter pack of T values representing the sequence +template +struct integer_sequence { + using value_type = T; + static constexpr size_t size() noexcept { return sizeof...(Ints); } +}; + +// Equivalent to std::index_sequence. +// +// Alias for an integer_sequence of size_t. +template +using index_sequence = integer_sequence; + +namespace utility_internal { + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> { + using type = integer_sequence; +}; + +template +struct Extend, SeqSize, 1> { + using type = integer_sequence; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen { + using type = + typename Extend::type, N / 2, N % 2>::type; +}; + +template +struct Gen { + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// Equivalent to std::make_integer_sequence. +// +// make_integer_sequence is integer_sequence; +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// Equivalent to std::make_index_sequence. +// +// make_index_sequence is index_sequence<0, 1, ..., N-1>; +template +using make_index_sequence = make_integer_sequence; + +// Equivalent to std::index_sequence_for. +// +// Convert a typename pack into an index sequence of the same length. +template +using index_sequence_for = make_index_sequence; + +// Tag types + +#ifdef ABSL_HAVE_STD_OPTIONAL + +using std::in_place_t; +using std::in_place; + +#else // ABSL_HAVE_STD_OPTIONAL + +// Tag type used in order to specify in-place construction, such as with +// absl::optional. +struct in_place_t {}; +extern const in_place_t in_place; + +#endif // ABSL_HAVE_STD_OPTIONAL + +#ifdef ABSL_HAVE_STD_ANY +using std::in_place_type_t; +#else +// Tag types used for in-place construction when the type to construct needs to +// be specified, such as with absl::variant and absl::any. +template +struct in_place_type_t {}; +#endif // ABSL_HAVE_STD_ANY + +template +struct in_place_index_t {}; + +// Constexpr move and forward + +template +constexpr absl::remove_reference_t&& move(T&& t) noexcept { + return static_cast&&>(t); +} + +template +constexpr T&& forward( + absl::remove_reference_t& t) noexcept { // NOLINT(runtime/references) + return static_cast(t); +} + +} // namespace absl + +#endif // ABSL_UTILITY_UTILITY_H_ diff --git a/absl/utility/utility_test.cc b/absl/utility/utility_test.cc new file mode 100644 index 0000000..62cb46f --- /dev/null +++ b/absl/utility/utility_test.cc @@ -0,0 +1,163 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 "absl/utility/utility.h" + +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/attributes.h" + +namespace { + +#ifdef _MSC_VER +// Warnings for unused variables in this test are false positives. On other +// platforms, they are suppressed by ABSL_ATTRIBUTE_UNUSED, but that doesn't +// work on MSVC. +// Both the unused variables and the name length warnings are due to calls +// to absl::make_index_sequence with very large values, creating very long type +// names. The resulting warnings are so long they make build output unreadable. +#pragma warning( push ) +#pragma warning( disable : 4503 ) // decorated name length exceeded +#pragma warning( disable : 4101 ) // unreferenced local variable +#endif // _MSC_VER + +using testing::StaticAssertTypeEq; +using testing::ElementsAre; + +TEST(IntegerSequenceTest, ValueType) { + StaticAssertTypeEq::value_type>(); + StaticAssertTypeEq::value_type>(); +} + +TEST(IntegerSequenceTest, Size) { + EXPECT_EQ(0, (absl::integer_sequence::size())); + EXPECT_EQ(1, (absl::integer_sequence::size())); + EXPECT_EQ(1, (absl::integer_sequence::size())); + EXPECT_EQ(2, (absl::integer_sequence::size())); + EXPECT_EQ(3, (absl::integer_sequence::size())); + EXPECT_EQ(3, (absl::integer_sequence::size())); + constexpr size_t sz = absl::integer_sequence::size(); + EXPECT_EQ(2, sz); +} + +TEST(IntegerSequenceTest, MakeIndexSequence) { + StaticAssertTypeEq, absl::make_index_sequence<0>>(); + StaticAssertTypeEq, absl::make_index_sequence<1>>(); + StaticAssertTypeEq, + absl::make_index_sequence<2>>(); + StaticAssertTypeEq, + absl::make_index_sequence<3>>(); +} + +TEST(IntegerSequenceTest, MakeIntegerSequence) { + StaticAssertTypeEq, + absl::make_integer_sequence>(); + StaticAssertTypeEq, + absl::make_integer_sequence>(); + StaticAssertTypeEq, + absl::make_integer_sequence>(); + StaticAssertTypeEq, + absl::make_integer_sequence>(); +} + +template +class Counter {}; + +template +void CountAll(absl::index_sequence) { + // We only need an alias here, but instantiate a variable to silence warnings + // for unused typedefs in some compilers. + ABSL_ATTRIBUTE_UNUSED Counter...> seq; +} + +// This test verifies that absl::make_index_sequence can handle large arguments +// without blowing up template instantiation stack, going OOM or taking forever +// to compile (there is hard 15 minutes limit imposed by forge). +TEST(IntegerSequenceTest, MakeIndexSequencePerformance) { + // O(log N) template instantiations. + // We only need an alias here, but instantiate a variable to silence warnings + // for unused typedefs in some compilers. + ABSL_ATTRIBUTE_UNUSED absl::make_index_sequence<(1 << 16) - 1> seq; + // O(N) template instantiations. + CountAll(absl::make_index_sequence<(1 << 8) - 1>()); +} + +template +auto ApplyFromTupleImpl(F f, const Tup& tup, absl::index_sequence) + -> decltype(f(std::get(tup)...)) { + return f(std::get(tup)...); +} + +template +using TupIdxSeq = absl::make_index_sequence::value>; + +template +auto ApplyFromTuple(F f, const Tup& tup) + -> decltype(ApplyFromTupleImpl(f, tup, TupIdxSeq{})) { + return ApplyFromTupleImpl(f, tup, TupIdxSeq{}); +} + +template +std::string Fmt(const T& x) { + std::ostringstream os; + os << x; + return os.str(); +} + +struct PoorStrCat { + template + std::string operator()(const Args&... args) const { + std::string r; + for (const auto& e : {Fmt(args)...}) r += e; + return r; + } +}; + +template +std::vector TupStringVecImpl(const Tup& tup, + absl::index_sequence) { + return {Fmt(std::get(tup))...}; +} + +template +std::vector TupStringVec(const std::tuple& tup) { + return TupStringVecImpl(tup, absl::index_sequence_for()); +} + +TEST(MakeIndexSequenceTest, ApplyFromTupleExample) { + PoorStrCat f{}; + EXPECT_EQ("12abc3.14", f(12, "abc", 3.14)); + EXPECT_EQ("12abc3.14", ApplyFromTuple(f, std::make_tuple(12, "abc", 3.14))); +} + +TEST(IndexSequenceForTest, Basic) { + StaticAssertTypeEq, absl::index_sequence_for<>>(); + StaticAssertTypeEq, absl::index_sequence_for>(); + StaticAssertTypeEq, + absl::index_sequence_for>(); +} + +TEST(IndexSequenceForTest, Example) { + EXPECT_THAT(TupStringVec(std::make_tuple(12, "abc", 3.14)), + ElementsAre("12", "abc", "3.14")); +} + +} // namespace + -- cgit v1.2.3