summaryrefslogtreecommitdiff
path: root/absl/types
diff options
context:
space:
mode:
Diffstat (limited to 'absl/types')
-rw-r--r--absl/types/BUILD.bazel69
-rw-r--r--absl/types/CMakeLists.txt462
-rw-r--r--absl/types/any.h12
-rw-r--r--absl/types/any_exception_safety_test.cc3
-rw-r--r--absl/types/any_test.cc70
-rw-r--r--absl/types/bad_any_cast.cc6
-rw-r--r--absl/types/bad_any_cast.h10
-rw-r--r--absl/types/bad_optional_access.cc6
-rw-r--r--absl/types/bad_optional_access.h10
-rw-r--r--absl/types/bad_variant_access.cc6
-rw-r--r--absl/types/bad_variant_access.h10
-rw-r--r--absl/types/compare.h510
-rw-r--r--absl/types/compare_test.cc313
-rw-r--r--absl/types/internal/optional.h396
-rw-r--r--absl/types/internal/span.h128
-rw-r--r--absl/types/internal/variant.h74
-rw-r--r--absl/types/optional.cc26
-rw-r--r--absl/types/optional.h454
-rw-r--r--absl/types/optional_exception_safety_test.cc6
-rw-r--r--absl/types/optional_test.cc90
-rw-r--r--absl/types/span.h221
-rw-r--r--absl/types/span_test.cc57
-rw-r--r--absl/types/variant.h33
-rw-r--r--absl/types/variant_benchmark.cc6
-rw-r--r--absl/types/variant_exception_safety_test.cc15
-rw-r--r--absl/types/variant_test.cc242
26 files changed, 2273 insertions, 962 deletions
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index d56fea6e..66ecb044 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -5,7 +5,7 @@
# 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
+# https://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,
@@ -15,11 +15,12 @@
#
load(
- "//absl:copts.bzl",
+ "//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
- "ABSL_TEST_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_EXCEPTIONS_FLAG",
"ABSL_EXCEPTIONS_FLAG_LINKOPTS",
+ "ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
@@ -30,6 +31,7 @@ cc_library(
name = "any",
hdrs = ["any.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_any_cast",
"//absl/base:config",
@@ -43,6 +45,7 @@ cc_library(
name = "bad_any_cast",
hdrs = ["bad_any_cast.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_any_cast_impl",
"//absl/base:config",
@@ -56,7 +59,7 @@ cc_library(
"bad_any_cast.h",
],
copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
"//absl/base",
@@ -71,7 +74,7 @@ cc_test(
"any_test.cc",
],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
"//absl/base",
@@ -89,6 +92,7 @@ cc_test(
"any_test.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
"//absl/base",
@@ -103,7 +107,7 @@ cc_test(
name = "any_exception_safety_test",
srcs = ["any_exception_safety_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
"//absl/base:exception_safety_testing",
@@ -113,8 +117,14 @@ cc_test(
cc_library(
name = "span",
- hdrs = ["span.h"],
+ srcs = [
+ "internal/span.h",
+ ],
+ hdrs = [
+ "span.h",
+ ],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/algorithm",
"//absl/base:core_headers",
@@ -128,7 +138,7 @@ cc_test(
size = "small",
srcs = ["span_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":span",
"//absl/base:config",
@@ -147,6 +157,7 @@ cc_test(
size = "small",
srcs = ["span_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":span",
"//absl/base:config",
@@ -162,11 +173,13 @@ cc_test(
cc_library(
name = "optional",
- srcs = ["optional.cc"],
+ srcs = ["internal/optional.h"],
hdrs = ["optional.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_optional_access",
+ "//absl/base:base_internal",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
@@ -180,7 +193,7 @@ cc_library(
srcs = ["bad_optional_access.cc"],
hdrs = ["bad_optional_access.h"],
copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base",
"//absl/base:config",
@@ -192,7 +205,7 @@ cc_library(
srcs = ["bad_variant_access.cc"],
hdrs = ["bad_variant_access.h"],
copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base",
"//absl/base:config",
@@ -206,7 +219,7 @@ cc_test(
"optional_test.cc",
],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":optional",
"//absl/base",
@@ -223,7 +236,7 @@ cc_test(
"optional_exception_safety_test.cc",
],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":optional",
"//absl/base:exception_safety_testing",
@@ -236,6 +249,7 @@ cc_library(
srcs = ["internal/variant.h"],
hdrs = ["variant.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_variant_access",
"//absl/base:base_internal",
@@ -251,7 +265,7 @@ cc_test(
size = "small",
srcs = ["variant_test.cc"],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":variant",
"//absl/base:config",
@@ -269,6 +283,7 @@ cc_test(
"variant_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":variant",
@@ -284,7 +299,7 @@ cc_test(
"variant_exception_safety_test.cc",
],
copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
deps = [
":variant",
"//absl/base:config",
@@ -293,3 +308,27 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "compare",
+ hdrs = ["compare.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_test(
+ name = "compare_test",
+ size = "small",
+ srcs = [
+ "compare_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":compare",
+ "//absl/base",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index e8620766..4ce685da 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -5,7 +5,7 @@
# 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
+# https://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,
@@ -13,216 +13,336 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-list(APPEND TYPES_PUBLIC_HEADERS
- "any.h"
- "bad_any_cast.h"
- "bad_optional_access.h"
- "optional.h"
- "span.h"
- "variant.h"
+absl_cc_library(
+ NAME
+ any
+ HDRS
+ "any.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_any_cast
+ absl::config
+ absl::core_headers
+ absl::type_traits
+ absl::utility
+ PUBLIC
)
+absl_cc_library(
+ NAME
+ bad_any_cast
+ HDRS
+ "bad_any_cast.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_any_cast_impl
+ absl::config
+ PUBLIC
+)
-# any library
-absl_header_library(
- TARGET
- absl_any
- PUBLIC_LIBRARIES
- absl::bad_any_cast
- absl::base
- absl::meta
- absl::utility
- PRIVATE_COMPILE_FLAGS
+absl_cc_library(
+ NAME
+ bad_any_cast_impl
+ SRCS
+ "bad_any_cast.h"
+ "bad_any_cast.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
${ABSL_EXCEPTIONS_FLAG}
- EXPORT_NAME
- any
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
)
-# span library
-absl_header_library(
- TARGET
- absl_span
- PUBLIC_LIBRARIES
- absl::utility
- EXPORT_NAME
- span
+absl_cc_test(
+ NAME
+ any_test
+ SRCS
+ "any_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::any
+ absl::base
+ absl::config
+ absl::exception_testing
+ absl::test_instance_tracker
+ gmock_main
)
+absl_cc_test(
+ NAME
+ any_test_noexceptions
+ SRCS
+ "any_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::any
+ absl::base
+ absl::config
+ absl::exception_testing
+ absl::test_instance_tracker
+ gmock_main
+)
-# bad_any_cast library
-list(APPEND BAD_ANY_CAST_SRC
- "bad_any_cast.cc"
- ${TYPES_PUBLIC_HEADERS}
+absl_cc_test(
+ NAME
+ any_exception_safety_test
+ SRCS
+ "any_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::any
+ absl::exception_safety_testing
+ gmock_main
)
-absl_library(
- TARGET
- absl_bad_any_cast
- SOURCES
- ${BAD_ANY_CAST_SRC}
- PUBLIC_LIBRARIES
- EXPORT_NAME
- bad_any_cast
+absl_cc_library(
+ NAME
+ span
+ HDRS
+ "span.h"
+ SRCS
+ "internal/span.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::algorithm
+ absl::core_headers
+ absl::throw_delegate
+ absl::type_traits
+ PUBLIC
)
+absl_cc_test(
+ NAME
+ span_test
+ SRCS
+ "span_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::span
+ absl::base
+ absl::config
+ absl::core_headers
+ absl::exception_testing
+ absl::fixed_array
+ absl::inlined_vector
+ absl::hash_testing
+ absl::strings
+ gmock_main
+)
-# optional library
-list(APPEND OPTIONAL_SRC
- "optional.cc"
+absl_cc_test(
+ NAME
+ span_test_noexceptions
+ SRCS
+ "span_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::span
+ absl::base
+ absl::config
+ absl::core_headers
+ absl::exception_testing
+ absl::fixed_array
+ absl::inlined_vector
+ absl::hash_testing
+ absl::strings
+ gmock_main
)
-absl_library(
- TARGET
- absl_optional
- SOURCES
- ${OPTIONAL_SRC}
- PUBLIC_LIBRARIES
+absl_cc_library(
+ NAME
+ optional
+ HDRS
+ "optional.h"
+ SRCS
+ "internal/optional.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
absl::bad_optional_access
- absl::base
+ absl::base_internal
+ absl::config
+ absl::core_headers
absl::memory
- absl::meta
+ absl::type_traits
absl::utility
- EXPORT_NAME
- optional
+ PUBLIC
)
-
-set(BAD_OPTIONAL_ACCESS_SRC "bad_optional_access.cc")
-set(BAD_OPTIONAL_ACCESS_LIBRARIES absl::base)
-
-absl_library(
- TARGET
- absl_bad_optional_access
- SOURCES
- ${BAD_OPTIONAL_ACCESS_SRC}
- PUBLIC_LIBRARIES
- ${BAD_OPTIONAL_ACCESS_PUBLIC_LIBRARIES}
- EXPORT_NAME
+absl_cc_library(
+ NAME
bad_optional_access
-)
-
-# variant library
-absl_library(
- TARGET
- absl_variant
- SOURCES
- "bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
- PUBLIC_LIBRARIES
- absl::base absl::meta absl::utility
- PRIVATE_COMPILE_FLAGS
+ HDRS
+ "bad_optional_access.h"
+ SRCS
+ "bad_optional_access.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
${ABSL_EXCEPTIONS_FLAG}
- EXPORT_NAME
- variant
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
+ PUBLIC
)
-#
-## TESTS
-#
-
-
-# test any_test
-set(ANY_TEST_SRC "any_test.cc")
-set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::any absl::bad_any_cast absl::test_instance_tracker)
-
-absl_test(
- TARGET
- any_test
- SOURCES
- ${ANY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+absl_cc_library(
+ NAME
+ bad_variant_access
+ HDRS
+ "bad_variant_access.h"
+ SRCS
+ "bad_variant_access.cc"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::base
+ absl::config
+ PUBLIC
)
-
-# test any_test_noexceptions
-absl_test(
- TARGET
- any_test_noexceptions
- SOURCES
- ${ANY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_TEST_PUBLIC_LIBRARIES}
-)
-
-# test any_exception_safety_test
-set(ANY_EXCEPTION_SAFETY_TEST_SRC "any_exception_safety_test.cc")
-set(ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
- absl::any
- absl::base
- absl_internal_exception_safety_testing
-)
-
-absl_test(
- TARGET
- any_exception_safety_test
- SOURCES
- ${ANY_EXCEPTION_SAFETY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+absl_cc_test(
+ NAME
+ optional_test
+ SRCS
+ "optional_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::optional
+ absl::base
+ absl::config
+ absl::type_traits
+ absl::strings
+ gmock_main
)
-
-# test span_test
-set(SPAN_TEST_SRC "span_test.cc")
-set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl_internal_throw_delegate absl::span absl::test_instance_tracker)
-
-absl_test(
- TARGET
- span_test
- SOURCES
- ${SPAN_TEST_SRC}
- PUBLIC_LIBRARIES
- ${SPAN_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+absl_cc_test(
+ NAME
+ optional_exception_safety_test
+ SRCS
+ "optional_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::optional
+ absl::exception_safety_testing
+ gmock_main
)
-
-# test span_test_noexceptions
-absl_test(
- TARGET
- span_test_noexceptions
- SOURCES
- ${SPAN_TEST_SRC}
- PUBLIC_LIBRARIES
- ${SPAN_TEST_PUBLIC_LIBRARIES}
+absl_cc_library(
+ NAME
+ variant
+ HDRS
+ "variant.h"
+ SRCS
+ "internal/variant.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::bad_variant_access
+ absl::base_internal
+ absl::config
+ absl::core_headers
+ absl::type_traits
+ absl::utility
+ PUBLIC
)
-
-
-# test optional_test
-set(OPTIONAL_TEST_SRC "optional_test.cc")
-set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl_internal_throw_delegate absl::optional absl_bad_optional_access)
-
-absl_test(
- TARGET
- optional_test
- SOURCES
- ${OPTIONAL_TEST_SRC}
- PUBLIC_LIBRARIES
- ${OPTIONAL_TEST_PUBLIC_LIBRARIES}
+absl_cc_test(
+ NAME
+ variant_test
+ SRCS
+ "variant_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ ${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::variant
+ absl::config
+ absl::core_headers
+ absl::memory
+ absl::type_traits
+ absl::strings
+ gmock_main
)
+absl_cc_library(
+ NAME
+ compare
+ HDRS
+ "compare.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ DEPS
+ absl::core_headers
+ absl::type_traits
+ PUBLIC
+)
-# test optional_exception_safety_test
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
- absl::optional
- absl_internal_exception_safety_testing
+absl_cc_test(
+ NAME
+ compare_test
+ SRCS
+ "compare_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::base
+ absl::compare
+ gmock_main
)
-absl_test(
- TARGET
- optional_exception_safety_test
- SOURCES
- ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
- PUBLIC_LIBRARIES
- ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
- PRIVATE_COMPILE_FLAGS
+# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
+else()
+absl_cc_test(
+ NAME
+ variant_exception_safety_test
+ SRCS
+ "variant_exception_safety_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
${ABSL_EXCEPTIONS_FLAG}
+ LINKOPTS
+ ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+ DEPS
+ absl::variant
+ absl::config
+ absl::exception_safety_testing
+ absl::memory
+ gmock_main
)
+endif()
diff --git a/absl/types/any.h b/absl/types/any.h
index dc3bfcfe..7cae9dd0 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -5,7 +5,7 @@
// 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
+// https://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,
@@ -58,15 +58,15 @@
#ifdef ABSL_HAVE_STD_ANY
-#include <any>
+#include <any> // IWYU pragma: export
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::any;
using std::any_cast;
using std::bad_any_cast;
using std::make_any;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_ANY
@@ -93,7 +93,7 @@ using std::make_any;
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace any_internal {
@@ -533,7 +533,7 @@ T* any_cast(any* operand) noexcept {
: nullptr;
}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#undef ABSL_ANY_DETAIL_HAS_RTTI
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
index f9dd8c48..5d7d8a5c 100644
--- a/absl/types/any_exception_safety_test.cc
+++ b/absl/types/any_exception_safety_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -135,6 +135,7 @@ TEST(AnyExceptionSafety, Assignment) {
EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
EXPECT_TRUE(strong_empty_any_tester.Test(move));
}
+
// libstdc++ std::any fails this test
#if !defined(ABSL_HAVE_STD_ANY)
TEST(AnyExceptionSafety, Emplace) {
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc
index 115e78df..87104721 100644
--- a/absl/types/any_test.cc
+++ b/absl/types/any_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -154,6 +154,14 @@ TEST(AnyTest, InPlaceConstruction) {
EXPECT_EQ(5, v.value);
}
+TEST(AnyTest, InPlaceConstructionVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<IntMoveOnlyCopyOnly>, 5, MoveOnly(),
+ copy_only);
+ auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
+ EXPECT_EQ(5, v.value);
+}
+
TEST(AnyTest, InPlaceConstructionWithCV) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<const volatile IntMoveOnlyCopyOnly>(), 5,
@@ -162,12 +170,26 @@ TEST(AnyTest, InPlaceConstructionWithCV) {
EXPECT_EQ(5, v.value);
}
+TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<const volatile IntMoveOnlyCopyOnly>, 5,
+ MoveOnly(), copy_only);
+ auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
+ EXPECT_EQ(5, v.value);
+}
+
TEST(AnyTest, InPlaceConstructionWithFunction) {
absl::any o(absl::in_place_type_t<FunctionType>(), FunctionToEmplace);
FunctionType*& construction_result = absl::any_cast<FunctionType*&>(o);
EXPECT_EQ(&FunctionToEmplace, construction_result);
}
+TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) {
+ absl::any o(absl::in_place_type<FunctionType>, FunctionToEmplace);
+ auto& construction_result = absl::any_cast<FunctionType*&>(o);
+ EXPECT_EQ(&FunctionToEmplace, construction_result);
+}
+
TEST(AnyTest, InPlaceConstructionWithArray) {
ArrayType ar = {5, 42};
absl::any o(absl::in_place_type_t<ArrayType>(), ar);
@@ -175,6 +197,13 @@ TEST(AnyTest, InPlaceConstructionWithArray) {
EXPECT_EQ(&ar[0], construction_result);
}
+TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) {
+ ArrayType ar = {5, 42};
+ absl::any o(absl::in_place_type<ArrayType>, ar);
+ auto& construction_result = absl::any_cast<DecayedArray&>(o);
+ EXPECT_EQ(&ar[0], construction_result);
+}
+
TEST(AnyTest, InPlaceConstructionIlist) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<ListMoveOnlyCopyOnly>(), {1, 2, 3, 4},
@@ -184,6 +213,15 @@ TEST(AnyTest, InPlaceConstructionIlist) {
EXPECT_EQ(expected_values, v.values);
}
+TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<ListMoveOnlyCopyOnly>, {1, 2, 3, 4},
+ MoveOnly(), copy_only);
+ auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
+ std::vector<int> expected_values = {1, 2, 3, 4};
+ EXPECT_EQ(expected_values, v.values);
+}
+
TEST(AnyTest, InPlaceConstructionIlistWithCV) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<const volatile ListMoveOnlyCopyOnly>(),
@@ -193,11 +231,25 @@ TEST(AnyTest, InPlaceConstructionIlistWithCV) {
EXPECT_EQ(expected_values, v.values);
}
+TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<const volatile ListMoveOnlyCopyOnly>,
+ {1, 2, 3, 4}, MoveOnly(), copy_only);
+ auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
+ std::vector<int> expected_values = {1, 2, 3, 4};
+ EXPECT_EQ(expected_values, v.values);
+}
+
TEST(AnyTest, InPlaceNoArgs) {
absl::any o(absl::in_place_type_t<int>{});
EXPECT_EQ(0, absl::any_cast<int&>(o));
}
+TEST(AnyTest, InPlaceNoArgsVariableTemplate) {
+ absl::any o(absl::in_place_type<int>);
+ EXPECT_EQ(0, absl::any_cast<int&>(o));
+}
+
template <typename Enabler, typename T, typename... Args>
struct CanEmplaceAnyImpl : std::false_type {};
@@ -501,7 +553,7 @@ TEST(AnyTest, Copy) {
InstanceTracker tracker_raii;
{
- absl::any o(absl::in_place_type_t<CopyableOnlyInstance>{}, 123);
+ absl::any o(absl::in_place_type<CopyableOnlyInstance>, 123);
CopyableOnlyInstance* f1 = absl::any_cast<CopyableOnlyInstance>(&o);
absl::any o2(o);
@@ -622,7 +674,7 @@ TEST(AnyTest, ThrowBadAlloc) {
}
{
- absl::any a(absl::in_place_type_t<int>{});
+ absl::any a(absl::in_place_type<int>);
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&>(a));
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(a));
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&&>(absl::any{}));
@@ -665,7 +717,7 @@ TEST(AnyTest, FailedCopy) {
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src});
}
@@ -677,21 +729,21 @@ TEST(AnyTest, FailedCopy) {
{
BadCopyable bad;
- absl::any target(absl::in_place_type_t<BadCopyable>{});
+ absl::any target(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad);
EXPECT_TRUE(target.has_value());
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
absl::any target;
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
EXPECT_FALSE(target.has_value());
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
- absl::any target(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
+ absl::any target(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
EXPECT_TRUE(target.has_value());
}
@@ -707,7 +759,7 @@ TEST(AnyTest, FailedEmplace) {
{
BadCopyable bad;
- absl::any target(absl::in_place_type_t<int>{});
+ absl::any target(absl::in_place_type<int>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad));
#if defined(ABSL_HAVE_STD_ANY) && defined(__GLIBCXX__)
// libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
index 6244d09e..062675df 100644
--- a/absl/types/bad_any_cast.cc
+++ b/absl/types/bad_any_cast.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -22,7 +22,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
bad_any_cast::~bad_any_cast() = default;
@@ -40,7 +40,7 @@ void ThrowBadAnyCast() {
}
} // namespace any_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_ANY
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 7df9afbb..8a8476ce 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -30,15 +30,15 @@
#include <any>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::bad_any_cast;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_ANY
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
// -----------------------------------------------------------------------------
// bad_any_cast
@@ -67,7 +67,7 @@ namespace any_internal {
[[noreturn]] void ThrowBadAnyCast();
} // namespace any_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_ANY
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
index 2dc74d3b..440adac2 100644
--- a/absl/types/bad_optional_access.cc
+++ b/absl/types/bad_optional_access.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -22,7 +22,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
bad_optional_access::~bad_optional_access() = default;
@@ -42,7 +42,7 @@ void throw_bad_optional_access() {
}
} // namespace optional_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_OPTIONAL
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index 1f56ff64..585c7c77 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -30,15 +30,15 @@
#include <optional>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::bad_optional_access;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_OPTIONAL
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
// -----------------------------------------------------------------------------
// bad_optional_access
@@ -70,7 +70,7 @@ namespace optional_internal {
[[noreturn]] void throw_bad_optional_access();
} // namespace optional_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_OPTIONAL
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
index a646ff53..d60dae9a 100644
--- a/absl/types/bad_variant_access.cc
+++ b/absl/types/bad_variant_access.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -23,7 +23,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
//////////////////////////
// [variant.bad.access] //
@@ -58,7 +58,7 @@ void Rethrow() {
}
} // namespace variant_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_VARIANT
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
index e0490842..8d635b57 100644
--- a/absl/types/bad_variant_access.h
+++ b/absl/types/bad_variant_access.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -30,15 +30,15 @@
#include <variant>
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::bad_variant_access;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_VARIANT
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
// -----------------------------------------------------------------------------
// bad_variant_access
@@ -74,7 +74,7 @@ namespace variant_internal {
[[noreturn]] void Rethrow();
} // namespace variant_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_HAVE_STD_VARIANT
diff --git a/absl/types/compare.h b/absl/types/compare.h
new file mode 100644
index 00000000..6f371be7
--- /dev/null
+++ b/absl/types/compare.h
@@ -0,0 +1,510 @@
+// Copyright 2018 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
+//
+// https://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.
+//
+// -----------------------------------------------------------------------------
+// compare.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::weak_equality`, `absl::strong_equality`,
+// `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering`
+// types for storing the results of three way comparisons.
+//
+// Example:
+// absl::weak_ordering compare(const std::string& a, const std::string& b);
+//
+// These are C++11 compatible versions of the C++20 corresponding types
+// (`std::weak_equality`, etc.) and are designed to be drop-in replacements
+// for code compliant with C++20.
+
+#ifndef ABSL_TYPES_COMPARE_H_
+#define ABSL_TYPES_COMPARE_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+inline namespace lts_2019_08_08 {
+namespace compare_internal {
+
+using value_type = int8_t;
+
+template <typename T>
+struct Fail {
+ static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
+};
+
+// We need the NullPtrT template to avoid triggering the modernize-use-nullptr
+// ClangTidy warning in user code.
+template <typename NullPtrT = std::nullptr_t>
+struct OnlyLiteralZero {
+ constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT
+
+ // Fails compilation when `nullptr` or integral type arguments other than
+ // `int` are passed. This constructor doesn't accept `int` because literal `0`
+ // has type `int`. Literal `0` arguments will be implicitly converted to
+ // `std::nullptr_t` and accepted by the above constructor, while other `int`
+ // arguments will fail to be converted and cause compilation failure.
+ template <
+ typename T,
+ typename = typename std::enable_if<
+ std::is_same<T, std::nullptr_t>::value ||
+ (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
+ typename = typename Fail<T>::type>
+ OnlyLiteralZero(T); // NOLINT
+};
+
+enum class eq : value_type {
+ equal = 0,
+ equivalent = equal,
+ nonequal = 1,
+ nonequivalent = nonequal,
+};
+
+enum class ord : value_type { less = -1, greater = 1 };
+
+enum class ncmp : value_type { unordered = -127 };
+
+// These template base classes allow for defining the values of the constants
+// in the header file (for performance) without using inline variables (which
+// aren't available in C++11).
+template <typename T>
+struct weak_equality_base {
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T nonequivalent;
+};
+template <typename T>
+const T weak_equality_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T weak_equality_base<T>::nonequivalent(eq::nonequivalent);
+
+template <typename T>
+struct strong_equality_base {
+ ABSL_CONST_INIT static const T equal;
+ ABSL_CONST_INIT static const T nonequal;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T nonequivalent;
+};
+template <typename T>
+const T strong_equality_base<T>::equal(eq::equal);
+template <typename T>
+const T strong_equality_base<T>::nonequal(eq::nonequal);
+template <typename T>
+const T strong_equality_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T strong_equality_base<T>::nonequivalent(eq::nonequivalent);
+
+template <typename T>
+struct partial_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+ ABSL_CONST_INIT static const T unordered;
+};
+template <typename T>
+const T partial_ordering_base<T>::less(ord::less);
+template <typename T>
+const T partial_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T partial_ordering_base<T>::greater(ord::greater);
+template <typename T>
+const T partial_ordering_base<T>::unordered(ncmp::unordered);
+
+template <typename T>
+struct weak_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+};
+template <typename T>
+const T weak_ordering_base<T>::less(ord::less);
+template <typename T>
+const T weak_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T weak_ordering_base<T>::greater(ord::greater);
+
+template <typename T>
+struct strong_ordering_base {
+ ABSL_CONST_INIT static const T less;
+ ABSL_CONST_INIT static const T equal;
+ ABSL_CONST_INIT static const T equivalent;
+ ABSL_CONST_INIT static const T greater;
+};
+template <typename T>
+const T strong_ordering_base<T>::less(ord::less);
+template <typename T>
+const T strong_ordering_base<T>::equal(eq::equal);
+template <typename T>
+const T strong_ordering_base<T>::equivalent(eq::equivalent);
+template <typename T>
+const T strong_ordering_base<T>::greater(ord::greater);
+
+} // namespace compare_internal
+
+class weak_equality
+ : public compare_internal::weak_equality_base<weak_equality> {
+ explicit constexpr weak_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_equality_base<weak_equality>;
+
+ public:
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 != v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class strong_equality
+ : public compare_internal::strong_equality_base<strong_equality> {
+ explicit constexpr strong_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_equality_base<strong_equality>;
+
+ public:
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 != v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class partial_ordering
+ : public compare_internal::partial_ordering_base<partial_ordering> {
+ explicit constexpr partial_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::partial_ordering_base<partial_ordering>;
+
+ constexpr bool is_ordered() const noexcept {
+ return value_ !=
+ compare_internal::value_type(compare_internal::ncmp::unordered);
+ }
+
+ public:
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return !v.is_ordered() || v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return !v.is_ordered() || 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class weak_ordering
+ : public compare_internal::weak_ordering_base<weak_ordering> {
+ explicit constexpr weak_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr weak_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_ordering_base<weak_ordering>;
+
+ public:
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+class strong_ordering
+ : public compare_internal::strong_ordering_base<strong_ordering> {
+ explicit constexpr strong_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr strong_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_ordering_base<strong_ordering>;
+
+ public:
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept { // NOLINT
+ return value_ == 0 ? strong_equality::equal : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept { // NOLINT
+ return value_ == 0
+ ? weak_ordering::equivalent
+ : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+
+namespace compare_internal {
+// We also provide these comparator adapter functions for internal absl use.
+
+// Helper functions to do a boolean comparison of two keys given a boolean
+// or three-way comparator.
+// SFINAE prevents implicit conversions to bool (such as from int).
+template <typename Bool,
+ absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0>
+constexpr bool compare_result_as_less_than(const Bool r) { return r; }
+constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
+ return r < 0;
+}
+
+template <typename Compare, typename K, typename LK>
+constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
+ const LK &y) {
+ return compare_result_as_less_than(compare(x, y));
+}
+
+// Helper functions to do a three-way comparison of two keys given a boolean or
+// three-way comparator.
+// SFINAE prevents implicit conversions to int (such as from bool).
+template <typename Int,
+ absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
+constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
+ return c < 0 ? absl::weak_ordering::less
+ : c == 0 ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+}
+constexpr absl::weak_ordering compare_result_as_ordering(
+ const absl::weak_ordering c) {
+ return c;
+}
+
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare_result_as_ordering(compare(x, y));
+}
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare(x, y) ? absl::weak_ordering::less
+ : compare(y, x) ? absl::weak_ordering::greater
+ : absl::weak_ordering::equivalent;
+}
+
+} // namespace compare_internal
+} // inline namespace lts_2019_08_08
+} // namespace absl
+
+#endif // ABSL_TYPES_COMPARE_H_
diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc
new file mode 100644
index 00000000..11b3ad40
--- /dev/null
+++ b/absl/types/compare_test.cc
@@ -0,0 +1,313 @@
+// Copyright 2018 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
+//
+// https://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/types/compare.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+
+namespace absl {
+inline namespace lts_2019_08_08 {
+namespace {
+
+// This is necessary to avoid a bunch of lint warnings suggesting that we use
+// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0`
+// to an int, which can't be converted to the unspecified zero type.
+bool Identity(bool b) { return b; }
+
+TEST(Compare, WeakEquality) {
+ EXPECT_TRUE(Identity(weak_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_equality::equivalent));
+ EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent));
+}
+
+TEST(Compare, StrongEquality) {
+ EXPECT_TRUE(Identity(strong_equality::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equal));
+ EXPECT_TRUE(Identity(strong_equality::nonequal != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequal));
+ EXPECT_TRUE(Identity(strong_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equivalent));
+ EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent));
+}
+
+TEST(Compare, PartialOrdering) {
+ EXPECT_TRUE(Identity(partial_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == partial_ordering::equivalent));
+ EXPECT_TRUE(Identity(partial_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::unordered != 0));
+ EXPECT_TRUE(Identity(0 != partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered < 0));
+ EXPECT_FALSE(Identity(0 < partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered <= 0));
+ EXPECT_FALSE(Identity(0 <= partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered > 0));
+ EXPECT_FALSE(Identity(0 > partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));
+ EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));
+}
+
+TEST(Compare, WeakOrdering) {
+ EXPECT_TRUE(Identity(weak_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_ordering::equivalent));
+ EXPECT_TRUE(Identity(weak_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < weak_ordering::greater));
+ EXPECT_TRUE(Identity(weak_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= weak_ordering::greater));
+}
+
+TEST(Compare, StrongOrdering) {
+ EXPECT_TRUE(Identity(strong_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equal));
+ EXPECT_TRUE(Identity(strong_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equivalent));
+ EXPECT_TRUE(Identity(strong_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < strong_ordering::greater));
+ EXPECT_TRUE(Identity(strong_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= strong_ordering::greater));
+}
+
+TEST(Compare, Conversions) {
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::nonequal) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equivalent) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(strong_equality::nonequivalent) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::less) != 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(partial_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::unordered) != 0));
+
+ EXPECT_TRUE(implicit_cast<weak_equality>(weak_ordering::less) != 0);
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<strong_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0));
+}
+
+struct WeakOrderingLess {
+ template <typename T>
+ absl::weak_ordering operator()(const T &a, const T &b) const {
+ return a < b ? absl::weak_ordering::less
+ : a == b ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+};
+
+TEST(CompareResultAsLessThan, SanityTest) {
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false));
+ EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true));
+
+ EXPECT_TRUE(
+ absl::compare_internal::compare_result_as_less_than(weak_ordering::less));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::equivalent));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::greater));
+}
+
+TEST(DoLessThanComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0));
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5));
+}
+
+TEST(CompareResultAsOrdering, SanityTest) {
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(-1) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(-1) == 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(0) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) < 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::compare_result_as_ordering(1) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) == 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) > 0));
+}
+
+TEST(DoThreeWayComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0));
+}
+
+} // namespace
+} // inline namespace lts_2019_08_08
+} // namespace absl
diff --git a/absl/types/internal/optional.h b/absl/types/internal/optional.h
new file mode 100644
index 00000000..3c8e7cca
--- /dev/null
+++ b/absl/types/internal/optional.h
@@ -0,0 +1,396 @@
+// 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
+//
+// https://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 ABSL_TYPES_INTERNAL_OPTIONAL_H_
+#define ABSL_TYPES_INTERNAL_OPTIONAL_H_
+
+#include <functional>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/inline_variable.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/utility/utility.h"
+
+// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+//
+// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
+// __cpp_inheriting_constructors is a predefined macro and a recommended way to
+// check for this language feature, but GCC doesn't support it until 5.0 and
+// Clang doesn't support it until 3.6.
+// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
+// constructor. For example, the following code won't work on MSVC 2015 Update3:
+// struct Base {
+// int t;
+// template <typename T>
+// constexpr Base(T t_) : t(t_) {}
+// };
+// struct Foo : Base {
+// using Base::Base;
+// }
+// constexpr Foo foo(0); // doesn't work on MSVC 2015
+#if defined(__clang__)
+#if __has_feature(cxx_inheriting_constructors)
+#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
+#endif
+#elif (defined(__GNUC__) && \
+ (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
+ (__cpp_inheriting_constructors >= 200802) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1910)
+#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
+#endif
+
+namespace absl {
+inline namespace lts_2019_08_08 {
+
+// Forward declaration
+template <typename T>
+class optional;
+
+namespace optional_internal {
+
+// This tag type is used as a constructor parameter type for `nullopt_t`.
+struct init_t {
+ explicit init_t() = default;
+};
+
+struct empty_struct {};
+
+// This class stores the data in optional<T>.
+// It is specialized based on whether T is trivially destructible.
+// This is the specialization for non trivially destructible type.
+template <typename T, bool unused = std::is_trivially_destructible<T>::value>
+class optional_data_dtor_base {
+ struct dummy_type {
+ static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
+ // Use an array to avoid GCC 6 placement-new warning.
+ empty_struct data[sizeof(T) / sizeof(empty_struct)];
+ };
+
+ protected:
+ // Whether there is data or not.
+ bool engaged_;
+ // Data storage
+ union {
+ dummy_type dummy_;
+ T data_;
+ };
+
+ void destruct() noexcept {
+ if (engaged_) {
+ data_.~T();
+ engaged_ = false;
+ }
+ }
+
+ // dummy_ must be initialized for constexpr constructor.
+ constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
+
+ template <typename... Args>
+ constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
+ : engaged_(true), data_(absl::forward<Args>(args)...) {}
+
+ ~optional_data_dtor_base() { destruct(); }
+};
+
+// Specialization for trivially destructible type.
+template <typename T>
+class optional_data_dtor_base<T, true> {
+ struct dummy_type {
+ static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
+ // Use array to avoid GCC 6 placement-new warning.
+ empty_struct data[sizeof(T) / sizeof(empty_struct)];
+ };
+
+ protected:
+ // Whether there is data or not.
+ bool engaged_;
+ // Data storage
+ union {
+ dummy_type dummy_;
+ T data_;
+ };
+ void destruct() noexcept { engaged_ = false; }
+
+ // dummy_ must be initialized for constexpr constructor.
+ constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
+
+ template <typename... Args>
+ constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
+ : engaged_(true), data_(absl::forward<Args>(args)...) {}
+};
+
+template <typename T>
+class optional_data_base : public optional_data_dtor_base<T> {
+ protected:
+ using base = optional_data_dtor_base<T>;
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using base::base;
+#else
+ optional_data_base() = default;
+
+ template <typename... Args>
+ constexpr explicit optional_data_base(in_place_t t, Args&&... args)
+ : base(t, absl::forward<Args>(args)...) {}
+#endif
+
+ template <typename... Args>
+ void construct(Args&&... args) {
+ // Use dummy_'s address to work around casting cv-qualified T* to void*.
+ ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
+ this->engaged_ = true;
+ }
+
+ template <typename U>
+ void assign(U&& u) {
+ if (this->engaged_) {
+ this->data_ = std::forward<U>(u);
+ } else {
+ construct(std::forward<U>(u));
+ }
+ }
+};
+
+// TODO(absl-team): Add another class using
+// std::is_trivially_move_constructible trait when available to match
+// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
+// have trivial move but nontrivial copy.
+// Also, we should be checking is_trivially_copyable here, which is not
+// supported now, so we use is_trivially_* traits instead.
+template <typename T,
+ bool unused = absl::is_trivially_copy_constructible<T>::value&&
+ absl::is_trivially_copy_assignable<typename std::remove_cv<
+ T>::type>::value&& std::is_trivially_destructible<T>::value>
+class optional_data;
+
+// Trivially copyable types
+template <typename T>
+class optional_data<T, true> : public optional_data_base<T> {
+ protected:
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using optional_data_base<T>::optional_data_base;
+#else
+ optional_data() = default;
+
+ template <typename... Args>
+ constexpr explicit optional_data(in_place_t t, Args&&... args)
+ : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
+#endif
+};
+
+template <typename T>
+class optional_data<T, false> : public optional_data_base<T> {
+ protected:
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using optional_data_base<T>::optional_data_base;
+#else
+ template <typename... Args>
+ constexpr explicit optional_data(in_place_t t, Args&&... args)
+ : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
+#endif
+
+ optional_data() = default;
+
+ optional_data(const optional_data& rhs) : optional_data_base<T>() {
+ if (rhs.engaged_) {
+ this->construct(rhs.data_);
+ }
+ }
+
+ optional_data(optional_data&& rhs) noexcept(
+ absl::default_allocator_is_nothrow::value ||
+ std::is_nothrow_move_constructible<T>::value)
+ : optional_data_base<T>() {
+ if (rhs.engaged_) {
+ this->construct(std::move(rhs.data_));
+ }
+ }
+
+ optional_data& operator=(const optional_data& rhs) {
+ if (rhs.engaged_) {
+ this->assign(rhs.data_);
+ } else {
+ this->destruct();
+ }
+ return *this;
+ }
+
+ optional_data& operator=(optional_data&& rhs) noexcept(
+ std::is_nothrow_move_assignable<T>::value&&
+ std::is_nothrow_move_constructible<T>::value) {
+ if (rhs.engaged_) {
+ this->assign(std::move(rhs.data_));
+ } else {
+ this->destruct();
+ }
+ return *this;
+ }
+};
+
+// Ordered by level of restriction, from low to high.
+// Copyable implies movable.
+enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
+
+// Base class for enabling/disabling copy/move constructor.
+template <copy_traits>
+class optional_ctor_base;
+
+template <>
+class optional_ctor_base<copy_traits::copyable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = default;
+ optional_ctor_base(optional_ctor_base&&) = default;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+template <>
+class optional_ctor_base<copy_traits::movable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = delete;
+ optional_ctor_base(optional_ctor_base&&) = default;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+template <>
+class optional_ctor_base<copy_traits::non_movable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = delete;
+ optional_ctor_base(optional_ctor_base&&) = delete;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+// Base class for enabling/disabling copy/move assignment.
+template <copy_traits>
+class optional_assign_base;
+
+template <>
+class optional_assign_base<copy_traits::copyable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = default;
+ optional_assign_base& operator=(optional_assign_base&&) = default;
+};
+
+template <>
+class optional_assign_base<copy_traits::movable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = delete;
+ optional_assign_base& operator=(optional_assign_base&&) = default;
+};
+
+template <>
+class optional_assign_base<copy_traits::non_movable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = delete;
+ optional_assign_base& operator=(optional_assign_base&&) = delete;
+};
+
+template <typename T>
+struct ctor_copy_traits {
+ static constexpr copy_traits traits =
+ std::is_copy_constructible<T>::value
+ ? copy_traits::copyable
+ : std::is_move_constructible<T>::value ? copy_traits::movable
+ : copy_traits::non_movable;
+};
+
+template <typename T>
+struct assign_copy_traits {
+ static constexpr copy_traits traits =
+ absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
+ ? copy_traits::copyable
+ : absl::is_move_assignable<T>::value &&
+ std::is_move_constructible<T>::value
+ ? copy_traits::movable
+ : copy_traits::non_movable;
+};
+
+// Whether T is constructible or convertible from optional<U>.
+template <typename T, typename U>
+struct is_constructible_convertible_from_optional
+ : std::integral_constant<
+ bool, std::is_constructible<T, optional<U>&>::value ||
+ std::is_constructible<T, optional<U>&&>::value ||
+ std::is_constructible<T, const optional<U>&>::value ||
+ std::is_constructible<T, const optional<U>&&>::value ||
+ std::is_convertible<optional<U>&, T>::value ||
+ std::is_convertible<optional<U>&&, T>::value ||
+ std::is_convertible<const optional<U>&, T>::value ||
+ std::is_convertible<const optional<U>&&, T>::value> {};
+
+// Whether T is constructible or convertible or assignable from optional<U>.
+template <typename T, typename U>
+struct is_constructible_convertible_assignable_from_optional
+ : std::integral_constant<
+ bool, is_constructible_convertible_from_optional<T, U>::value ||
+ std::is_assignable<T&, optional<U>&>::value ||
+ std::is_assignable<T&, optional<U>&&>::value ||
+ std::is_assignable<T&, const optional<U>&>::value ||
+ std::is_assignable<T&, const optional<U>&&>::value> {};
+
+// Helper function used by [optional.relops], [optional.comp_with_t],
+// for checking whether an expression is convertible to bool.
+bool convertible_to_bool(bool);
+
+// Base class for std::hash<absl::optional<T>>:
+// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
+// compute the hash; Otherwise, it is disabled.
+// Reference N4659 23.14.15 [unord.hash].
+template <typename T, typename = size_t>
+struct optional_hash_base {
+ optional_hash_base() = delete;
+ optional_hash_base(const optional_hash_base&) = delete;
+ optional_hash_base(optional_hash_base&&) = delete;
+ optional_hash_base& operator=(const optional_hash_base&) = delete;
+ optional_hash_base& operator=(optional_hash_base&&) = delete;
+};
+
+template <typename T>
+struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
+ std::declval<absl::remove_const_t<T> >()))> {
+ using argument_type = absl::optional<T>;
+ using result_type = size_t;
+ size_t operator()(const absl::optional<T>& opt) const {
+ absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
+ if (opt) {
+ return std::hash<absl::remove_const_t<T> >()(*opt);
+ } else {
+ return static_cast<size_t>(0x297814aaad196e6dULL);
+ }
+ }
+};
+
+} // namespace optional_internal
+} // inline namespace lts_2019_08_08
+} // namespace absl
+
+#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+
+#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h
new file mode 100644
index 00000000..873ae160
--- /dev/null
+++ b/absl/types/internal/span.h
@@ -0,0 +1,128 @@
+//
+// Copyright 2019 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
+//
+// https://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 ABSL_TYPES_INTERNAL_SPAN_H_
+#define ABSL_TYPES_INTERNAL_SPAN_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <string>
+#include <type_traits>
+
+#include "absl/algorithm/algorithm.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+inline namespace lts_2019_08_08 {
+
+namespace span_internal {
+// A constexpr min function
+constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
+
+// Wrappers for access to container data pointers.
+template <typename C>
+constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
+ -> decltype(c.data()) {
+ return c.data();
+}
+
+// Before C++17, std::string::data returns a const char* in all cases.
+inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
+ int) noexcept {
+ return &s[0];
+}
+
+template <typename C>
+constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
+ -> decltype(GetDataImpl(c, 0)) {
+ return GetDataImpl(c, 0);
+}
+
+// Detection idioms for size() and data().
+template <typename C>
+using HasSize =
+ std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
+
+// We want to enable conversion from vector<T*> to Span<const T* const> but
+// disable conversion from vector<Derived> to Span<Base>. Here we use
+// the fact that U** is convertible to Q* const* if and only if Q is the same
+// type or a more cv-qualified version of U. We also decay the result type of
+// data() to avoid problems with classes which have a member function data()
+// which returns a reference.
+template <typename T, typename C>
+using HasData =
+ std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
+ T* const*>;
+
+// Extracts value type from a Container
+template <typename C>
+struct ElementType {
+ using type = typename absl::remove_reference_t<C>::value_type;
+};
+
+template <typename T, size_t N>
+struct ElementType<T (&)[N]> {
+ using type = T;
+};
+
+template <typename C>
+using ElementT = typename ElementType<C>::type;
+
+template <typename T>
+using EnableIfMutable =
+ typename std::enable_if<!std::is_const<T>::value, int>::type;
+
+template <template <typename> class SpanT, typename T>
+bool EqualImpl(SpanT<T> a, SpanT<T> b) {
+ static_assert(std::is_const<T>::value, "");
+ return absl::equal(a.begin(), a.end(), b.begin(), b.end());
+}
+
+template <template <typename> class SpanT, typename T>
+bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
+ // We can't use value_type since that is remove_cv_t<T>, so we go the long way
+ // around.
+ static_assert(std::is_const<T>::value, "");
+ return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+}
+
+// The `IsConvertible` classes here are needed because of the
+// `std::is_convertible` bug in libcxx when compiled with GCC. This build
+// configuration is used by Android NDK toolchain. Reference link:
+// https://bugs.llvm.org/show_bug.cgi?id=27538.
+template <typename From, typename To>
+struct IsConvertibleHelper {
+ private:
+ static std::true_type testval(To);
+ static std::false_type testval(...);
+
+ public:
+ using type = decltype(testval(std::declval<From>()));
+};
+
+template <typename From, typename To>
+struct IsConvertible : IsConvertibleHelper<From, To>::type {};
+
+// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
+// older version of libcxx is not supported.
+template <typename From, typename To>
+using EnableIfConvertibleTo =
+ typename std::enable_if<IsConvertible<From, To>::value>::type;
+} // namespace span_internal
+} // inline namespace lts_2019_08_08
+} // namespace absl
+
+#endif // ABSL_TYPES_INTERNAL_SPAN_H_
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 875f88e0..4f29f617 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -15,7 +15,6 @@
// Implementation details of absl/types/variant.h, pulled into a
// separate file to avoid cluttering the top of the API header with
// implementation details.
-//
#ifndef ABSL_TYPES_variant_internal_H_
#define ABSL_TYPES_variant_internal_H_
@@ -41,7 +40,7 @@
#if !defined(ABSL_HAVE_STD_VARIANT)
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
template <class... Types>
class variant;
@@ -206,7 +205,7 @@ template <class Op, class... Vs>
using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
template <class ReturnType, class FunctionObject, class EndIndices,
- std::size_t... BoundIndices>
+ class BoundIndices>
struct MakeVisitationMatrix;
template <class ReturnType, class FunctionObject, std::size_t... Indices>
@@ -220,7 +219,7 @@ constexpr ReturnType call_with_indices(FunctionObject&& function) {
template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
- BoundIndices...> {
+ index_sequence<BoundIndices...>> {
using ResultType = ReturnType (*)(FunctionObject&&);
static constexpr ResultType Run() {
return &call_with_indices<ReturnType, FunctionObject,
@@ -228,24 +227,34 @@ struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
}
};
+template <typename Is, std::size_t J>
+struct AppendToIndexSequence;
+
+template <typename Is, std::size_t J>
+using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type;
+
+template <std::size_t... Is, std::size_t J>
+struct AppendToIndexSequence<index_sequence<Is...>, J> {
+ using type = index_sequence<Is..., J>;
+};
+
template <class ReturnType, class FunctionObject, class EndIndices,
- class CurrIndices, std::size_t... BoundIndices>
+ class CurrIndices, class BoundIndices>
struct MakeVisitationMatrixImpl;
-template <class ReturnType, class FunctionObject, std::size_t... EndIndices,
- std::size_t... CurrIndices, std::size_t... BoundIndices>
-struct MakeVisitationMatrixImpl<
- ReturnType, FunctionObject, index_sequence<EndIndices...>,
- index_sequence<CurrIndices...>, BoundIndices...> {
+template <class ReturnType, class FunctionObject, class EndIndices,
+ std::size_t... CurrIndices, class BoundIndices>
+struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices,
+ index_sequence<CurrIndices...>, BoundIndices> {
using ResultType = SimpleArray<
- typename MakeVisitationMatrix<ReturnType, FunctionObject,
- index_sequence<EndIndices...>>::ResultType,
+ typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices,
+ index_sequence<>>::ResultType,
sizeof...(CurrIndices)>;
static constexpr ResultType Run() {
- return {{MakeVisitationMatrix<ReturnType, FunctionObject,
- index_sequence<EndIndices...>,
- BoundIndices..., CurrIndices>::Run()...}};
+ return {{MakeVisitationMatrix<
+ ReturnType, FunctionObject, EndIndices,
+ AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}};
}
};
@@ -253,10 +262,11 @@ template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
std::size_t... TailEndIndices, std::size_t... BoundIndices>
struct MakeVisitationMatrix<ReturnType, FunctionObject,
index_sequence<HeadEndIndex, TailEndIndices...>,
- BoundIndices...>
- : MakeVisitationMatrixImpl<
- ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
- absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
+ index_sequence<BoundIndices...>>
+ : MakeVisitationMatrixImpl<ReturnType, FunctionObject,
+ index_sequence<TailEndIndices...>,
+ absl::make_index_sequence<HeadEndIndex>,
+ index_sequence<BoundIndices...>> {};
struct UnreachableSwitchCase {
template <class Op>
@@ -425,7 +435,8 @@ struct VisitIndicesFallback {
static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
return AccessSimpleArray(
MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
- index_sequence<(EndIndices + 1)...>>::Run(),
+ index_sequence<(EndIndices + 1)...>,
+ index_sequence<>>::Run(),
(indices + 1)...)(absl::forward<Op>(op));
}
};
@@ -839,8 +850,8 @@ struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
// NOTE: const& and && are used instead of by-value due to lack of guaranteed
// move elision of C++17. This may have other minor differences, but tests
// pass.
- static SizeT<I> Run(const H&);
- static SizeT<I> Run(H&&);
+ static SizeT<I> Run(const H&, SizeT<I>);
+ static SizeT<I> Run(H&&, SizeT<I>);
};
// The following metafunctions are used in constructor and assignment
@@ -862,7 +873,8 @@ struct ConversionIsPossibleImpl : std::false_type {};
template <class Variant, class T>
struct ConversionIsPossibleImpl<
- Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
+ Variant, T,
+ void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
: std::true_type {};
template <class Variant, class T>
@@ -870,8 +882,9 @@ struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
template <class Variant, class T>
struct IndexOfConstructedType<
- Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
- : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
+ Variant, T,
+ void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
+ : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
template <std::size_t... Is>
struct ContainsVariantNPos
@@ -1550,8 +1563,8 @@ struct SwapSameIndex {
variant<Types...>* w;
template <std::size_t I>
void operator()(SizeT<I>) const {
- using std::swap;
- swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+ type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+ VariantCoreAccess::Access<I>(*w));
}
void operator()(SizeT<variant_npos>) const {}
@@ -1606,11 +1619,12 @@ struct VariantHashVisitor {
template <typename Variant, typename... Ts>
struct VariantHashBase<Variant,
absl::enable_if_t<absl::conjunction<
- type_traits_internal::IsHashEnabled<Ts>...>::value>,
+ type_traits_internal::IsHashable<Ts>...>::value>,
Ts...> {
using argument_type = Variant;
using result_type = size_t;
size_t operator()(const Variant& var) const {
+ type_traits_internal::AssertHashEnabled<Ts...>();
if (var.valueless_by_exception()) {
return 239799884;
}
@@ -1625,7 +1639,7 @@ struct VariantHashBase<Variant,
};
} // namespace variant_internal
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // !defined(ABSL_HAVE_STD_VARIANT)
diff --git a/absl/types/optional.cc b/absl/types/optional.cc
deleted file mode 100644
index 5c77f154..00000000
--- a/absl/types/optional.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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/types/optional.h"
-
-#ifndef ABSL_HAVE_STD_OPTIONAL
-namespace absl {
-inline namespace lts_2018_12_18 {
-
-nullopt_t::init_t nullopt_t::init;
-extern const nullopt_t nullopt{nullopt_t::init};
-
-} // inline namespace lts_2018_12_18
-} // namespace absl
-#endif // ABSL_HAVE_STD_OPTIONAL
diff --git a/absl/types/optional.h b/absl/types/optional.h
index 1ca8dec6..6614d7bd 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -35,21 +35,21 @@
#ifndef ABSL_TYPES_OPTIONAL_H_
#define ABSL_TYPES_OPTIONAL_H_
-#include "absl/base/config.h"
+#include "absl/base/config.h" // TODO(calabrese) IWYU removal?
#include "absl/utility/utility.h"
#ifdef ABSL_HAVE_STD_OPTIONAL
-#include <optional>
+#include <optional> // IWYU pragma: export
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::bad_optional_access;
using std::optional;
using std::make_optional;
using std::nullopt_t;
using std::nullopt;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_OPTIONAL
@@ -57,45 +57,33 @@ using std::nullopt;
#include <cassert>
#include <functional>
#include <initializer_list>
-#include <new>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
-#include "absl/memory/memory.h"
+#include "absl/base/internal/inline_variable.h"
#include "absl/meta/type_traits.h"
#include "absl/types/bad_optional_access.h"
+#include "absl/types/internal/optional.h"
-// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+namespace absl {
+inline namespace lts_2019_08_08 {
+
+// nullopt_t
//
-// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
-// __cpp_inheriting_constructors is a predefined macro and a recommended way to
-// check for this language feature, but GCC doesn't support it until 5.0 and
-// Clang doesn't support it until 3.6.
-// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
-// constructor. For example, the following code won't work on MSVC 2015 Update3:
-// struct Base {
-// int t;
-// template <typename T>
-// constexpr Base(T t_) : t(t_) {}
-// };
-// struct Foo : Base {
-// using Base::Base;
-// }
-// constexpr Foo foo(0); // doesn't work on MSVC 2015
-#if defined(__clang__)
-#if __has_feature(cxx_inheriting_constructors)
-#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
-#endif
-#elif (defined(__GNUC__) && \
- (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
- (__cpp_inheriting_constructors >= 200802) || \
- (defined(_MSC_VER) && _MSC_VER >= 1910)
-#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
-#endif
+// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
+// that does not contain a value.
+struct nullopt_t {
+ // It must not be default-constructible to avoid ambiguity for opt = {}.
+ explicit constexpr nullopt_t(optional_internal::init_t) noexcept {}
+};
-namespace absl {
-inline namespace lts_2018_12_18 {
+// nullopt
+//
+// A tag constant of type `absl::nullopt_t` used to indicate an empty
+// `absl::optional` in certain functions, such as construction or assignment.
+ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt,
+ nullopt_t(optional_internal::init_t()));
// -----------------------------------------------------------------------------
// absl::optional
@@ -117,10 +105,6 @@ inline namespace lts_2018_12_18 {
// need the inline variable support in C++17 for external linkage.
// * Throws `absl::bad_optional_access` instead of
// `std::bad_optional_access`.
-// * `optional::swap()` and `absl::swap()` relies on
-// `std::is_(nothrow_)swappable()`, which has been introduced in C++17.
-// As a workaround, we assume `is_swappable()` is always `true`
-// and `is_nothrow_swappable()` is the same as `std::is_trivial()`.
// * `make_optional()` cannot be declared `constexpr` due to the absence of
// guaranteed copy elision.
// * The move constructor's `noexcept` specification is stronger, i.e. if the
@@ -130,366 +114,13 @@ inline namespace lts_2018_12_18 {
// a) move constructors should only throw due to allocation failure and
// b) if T's move constructor allocates, it uses the same allocation
// function as the default allocator.
-template <typename T>
-class optional;
-
-// nullopt_t
-//
-// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
-// that does not contain a value.
-struct nullopt_t {
- struct init_t {};
- static init_t init;
-
- // It must not be default-constructible to avoid ambiguity for opt = {}.
- // Note the non-const reference, which is to eliminate ambiguity for code
- // like:
- //
- // struct S { int value; };
- //
- // void Test() {
- // optional<S> opt;
- // opt = {{}};
- // }
- explicit constexpr nullopt_t(init_t& /*unused*/) {}
-};
-
-// nullopt
//
-// A tag constant of type `absl::nullopt_t` used to indicate an empty
-// `absl::optional` in certain functions, such as construction or assignment.
-extern const nullopt_t nullopt;
-
-namespace optional_internal {
-
-struct empty_struct {};
-// This class stores the data in optional<T>.
-// It is specialized based on whether T is trivially destructible.
-// This is the specialization for non trivially destructible type.
-template <typename T, bool unused = std::is_trivially_destructible<T>::value>
-class optional_data_dtor_base {
- struct dummy_type {
- static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
- // Use an array to avoid GCC 6 placement-new warning.
- empty_struct data[sizeof(T) / sizeof(empty_struct)];
- };
-
- protected:
- // Whether there is data or not.
- bool engaged_;
- // Data storage
- union {
- dummy_type dummy_;
- T data_;
- };
-
- void destruct() noexcept {
- if (engaged_) {
- data_.~T();
- engaged_ = false;
- }
- }
-
- // dummy_ must be initialized for constexpr constructor.
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(absl::forward<Args>(args)...) {}
-
- ~optional_data_dtor_base() { destruct(); }
-};
-
-// Specialization for trivially destructible type.
-template <typename T>
-class optional_data_dtor_base<T, true> {
- struct dummy_type {
- static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
- // Use array to avoid GCC 6 placement-new warning.
- empty_struct data[sizeof(T) / sizeof(empty_struct)];
- };
-
- protected:
- // Whether there is data or not.
- bool engaged_;
- // Data storage
- union {
- dummy_type dummy_;
- T data_;
- };
- void destruct() noexcept { engaged_ = false; }
-
- // dummy_ must be initialized for constexpr constructor.
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(absl::forward<Args>(args)...) {}
-};
-
-template <typename T>
-class optional_data_base : public optional_data_dtor_base<T> {
- protected:
- using base = optional_data_dtor_base<T>;
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using base::base;
-#else
- optional_data_base() = default;
-
- template <typename... Args>
- constexpr explicit optional_data_base(in_place_t t, Args&&... args)
- : base(t, absl::forward<Args>(args)...) {}
-#endif
-
- template <typename... Args>
- void construct(Args&&... args) {
- // Use dummy_'s address to work around casting cv-qualified T* to void*.
- ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
- this->engaged_ = true;
- }
-
- template <typename U>
- void assign(U&& u) {
- if (this->engaged_) {
- this->data_ = std::forward<U>(u);
- } else {
- construct(std::forward<U>(u));
- }
- }
-};
-
-// TODO(absl-team): Add another class using
-// std::is_trivially_move_constructible trait when available to match
-// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
-// have trivial move but nontrivial copy.
-// Also, we should be checking is_trivially_copyable here, which is not
-// supported now, so we use is_trivially_* traits instead.
-template <typename T,
- bool unused = absl::is_trivially_copy_constructible<T>::value&&
- absl::is_trivially_copy_assignable<typename std::remove_cv<
- T>::type>::value&& std::is_trivially_destructible<T>::value>
-class optional_data;
-
-// Trivially copyable types
-template <typename T>
-class optional_data<T, true> : public optional_data_base<T> {
- protected:
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using optional_data_base<T>::optional_data_base;
-#else
- optional_data() = default;
-
- template <typename... Args>
- constexpr explicit optional_data(in_place_t t, Args&&... args)
- : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
-#endif
-};
-
-template <typename T>
-class optional_data<T, false> : public optional_data_base<T> {
- protected:
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using optional_data_base<T>::optional_data_base;
-#else
- template <typename... Args>
- constexpr explicit optional_data(in_place_t t, Args&&... args)
- : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
-#endif
-
- optional_data() = default;
-
- optional_data(const optional_data& rhs) {
- if (rhs.engaged_) {
- this->construct(rhs.data_);
- }
- }
-
- optional_data(optional_data&& rhs) noexcept(
- absl::default_allocator_is_nothrow::value ||
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- this->construct(std::move(rhs.data_));
- }
- }
-
- optional_data& operator=(const optional_data& rhs) {
- if (rhs.engaged_) {
- this->assign(rhs.data_);
- } else {
- this->destruct();
- }
- return *this;
- }
-
- optional_data& operator=(optional_data&& rhs) noexcept(
- std::is_nothrow_move_assignable<T>::value&&
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- this->assign(std::move(rhs.data_));
- } else {
- this->destruct();
- }
- return *this;
- }
-};
-
-// Ordered by level of restriction, from low to high.
-// Copyable implies movable.
-enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
-
-// Base class for enabling/disabling copy/move constructor.
-template <copy_traits>
-class optional_ctor_base;
-
-template <>
-class optional_ctor_base<copy_traits::copyable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = default;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::non_movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = delete;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-// Base class for enabling/disabling copy/move assignment.
-template <copy_traits>
-class optional_assign_base;
-
-template <>
-class optional_assign_base<copy_traits::copyable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = default;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::non_movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = delete;
-};
-
-template <typename T>
-constexpr copy_traits get_ctor_copy_traits() {
- return std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : std::is_move_constructible<T>::value ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-template <typename T>
-constexpr copy_traits get_assign_copy_traits() {
- return absl::is_copy_assignable<T>::value &&
- std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : absl::is_move_assignable<T>::value &&
- std::is_move_constructible<T>::value
- ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-// Whether T is constructible or convertible from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_from_optional
- : std::integral_constant<
- bool, std::is_constructible<T, optional<U>&>::value ||
- std::is_constructible<T, optional<U>&&>::value ||
- std::is_constructible<T, const optional<U>&>::value ||
- std::is_constructible<T, const optional<U>&&>::value ||
- std::is_convertible<optional<U>&, T>::value ||
- std::is_convertible<optional<U>&&, T>::value ||
- std::is_convertible<const optional<U>&, T>::value ||
- std::is_convertible<const optional<U>&&, T>::value> {};
-
-// Whether T is constructible or convertible or assignable from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_assignable_from_optional
- : std::integral_constant<
- bool, is_constructible_convertible_from_optional<T, U>::value ||
- std::is_assignable<T&, optional<U>&>::value ||
- std::is_assignable<T&, optional<U>&&>::value ||
- std::is_assignable<T&, const optional<U>&>::value ||
- std::is_assignable<T&, const optional<U>&&>::value> {};
-
-// Helper function used by [optional.relops], [optional.comp_with_t],
-// for checking whether an expression is convertible to bool.
-bool convertible_to_bool(bool);
-
-// Base class for std::hash<absl::optional<T>>:
-// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
-// compute the hash; Otherwise, it is disabled.
-// Reference N4659 23.14.15 [unord.hash].
-template <typename T, typename = size_t>
-struct optional_hash_base {
- optional_hash_base() = delete;
- optional_hash_base(const optional_hash_base&) = delete;
- optional_hash_base(optional_hash_base&&) = delete;
- optional_hash_base& operator=(const optional_hash_base&) = delete;
- optional_hash_base& operator=(optional_hash_base&&) = delete;
-};
-
-template <typename T>
-struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
- std::declval<absl::remove_const_t<T> >()))> {
- using argument_type = absl::optional<T>;
- using result_type = size_t;
- size_t operator()(const absl::optional<T>& opt) const {
- if (opt) {
- return std::hash<absl::remove_const_t<T> >()(*opt);
- } else {
- return static_cast<size_t>(0x297814aaad196e6dULL);
- }
- }
-};
-
-} // namespace optional_internal
-
-// -----------------------------------------------------------------------------
-// absl::optional class definition
-// -----------------------------------------------------------------------------
-
template <typename T>
class optional : private optional_internal::optional_data<T>,
private optional_internal::optional_ctor_base<
- optional_internal::get_ctor_copy_traits<T>()>,
+ optional_internal::ctor_copy_traits<T>::traits>,
private optional_internal::optional_assign_base<
- optional_internal::get_assign_copy_traits<T>()> {
+ optional_internal::assign_copy_traits<T>::traits> {
using data_base = optional_internal::optional_data<T>;
public:
@@ -514,10 +145,11 @@ class optional : private optional_internal::optional_data<T>,
// the arguments `std::forward<Args>(args)...` within the `optional`.
// (The `in_place_t` is a tag used to indicate that the contained object
// should be constructed in-place.)
- //
- // TODO(absl-team): Add std::is_constructible<T, Args&&...> SFINAE.
- template <typename... Args>
- constexpr explicit optional(in_place_t, Args&&... args)
+ template <typename InPlaceT, typename... Args,
+ absl::enable_if_t<absl::conjunction<
+ std::is_same<InPlaceT, in_place_t>,
+ std::is_constructible<T, Args&&...> >::value>* = nullptr>
+ constexpr explicit optional(InPlaceT, Args&&... args)
: data_base(in_place_t(), absl::forward<Args>(args)...) {}
// Constructs a non-empty `optional` direct-initialized value of type `T` from
@@ -753,11 +385,10 @@ class optional : private optional_internal::optional_data<T>,
// Swap, standard semantics
void swap(optional& rhs) noexcept(
std::is_nothrow_move_constructible<T>::value&&
- std::is_trivial<T>::value) {
+ type_traits_internal::IsNothrowSwappable<T>::value) {
if (*this) {
if (rhs) {
- using std::swap;
- swap(**this, *rhs);
+ type_traits_internal::Swap(**this, *rhs);
} else {
rhs.construct(std::move(**this));
this->destruct();
@@ -793,7 +424,9 @@ class optional : private optional_internal::optional_data<T>,
//
// Accesses the underlying `T` value of an `optional`. If the `optional` is
// empty, behavior is undefined.
- constexpr const T& operator*() const & { return reference(); }
+ constexpr const T& operator*() const& {
+ return ABSL_ASSERT(this->engaged_), reference();
+ }
T& operator*() & {
assert(this->engaged_);
return reference();
@@ -869,7 +502,7 @@ class optional : private optional_internal::optional_data<T>,
template <typename U>
constexpr T value_or(U&& v) const& {
static_assert(std::is_copy_constructible<value_type>::value,
- "optional<T>::value_or: T must by copy constructible");
+ "optional<T>::value_or: T must be copy constructible");
static_assert(std::is_convertible<U&&, value_type>::value,
"optional<T>::value_or: U must be convertible to T");
return static_cast<bool>(*this)
@@ -879,7 +512,7 @@ class optional : private optional_internal::optional_data<T>,
template <typename U>
T value_or(U&& v) && { // NOLINT(build/c++11)
static_assert(std::is_move_constructible<value_type>::value,
- "optional<T>::value_or: T must by copy constructible");
+ "optional<T>::value_or: T must be move constructible");
static_assert(std::is_convertible<U&&, value_type>::value,
"optional<T>::value_or: U must be convertible to T");
return static_cast<bool>(*this) ? std::move(**this)
@@ -909,12 +542,10 @@ class optional : private optional_internal::optional_data<T>,
//
// Performs a swap between two `absl::optional` objects, using standard
// semantics.
-//
-// NOTE: we assume `is_swappable()` is always `true`. A compile error will
-// result if this is not the case.
-template <typename T,
- typename std::enable_if<std::is_move_constructible<T>::value,
- bool>::type = false>
+template <typename T, typename std::enable_if<
+ std::is_move_constructible<T>::value &&
+ type_traits_internal::IsSwappable<T>::value,
+ bool>::type = false>
void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
@@ -1126,7 +757,7 @@ constexpr auto operator>=(const U& v, const optional<T>& x)
return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
namespace std {
@@ -1138,7 +769,6 @@ struct hash<absl::optional<T> >
} // namespace std
-#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
#endif // ABSL_HAVE_STD_OPTIONAL
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
index 313891f7..056ced42 100644
--- a/absl/types/optional_exception_safety_test.cc
+++ b/absl/types/optional_exception_safety_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -18,7 +18,7 @@
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace {
@@ -280,5 +280,5 @@ TEST(OptionalExceptionSafety, NothrowMoveAssign) {
} // namespace
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index fc4f00a4..e6a36eb8 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -157,6 +157,16 @@ struct NonMovable {
NonMovable& operator=(NonMovable&&) = delete;
};
+struct NoDefault {
+ NoDefault() = delete;
+ NoDefault(const NoDefault&) {}
+ NoDefault& operator=(const NoDefault&) { return *this; }
+};
+
+struct ConvertsFromInPlaceT {
+ ConvertsFromInPlaceT(absl::in_place_t) {} // NOLINT
+};
+
TEST(optionalTest, DefaultConstructor) {
absl::optional<int> empty;
EXPECT_FALSE(empty);
@@ -169,15 +179,7 @@ TEST(optionalTest, DefaultConstructor) {
TEST(optionalTest, nulloptConstructor) {
absl::optional<int> empty(absl::nullopt);
EXPECT_FALSE(empty);
-
-#ifdef ABSL_HAVE_STD_OPTIONAL
constexpr absl::optional<int> cempty{absl::nullopt};
-#else
- // Creating a temporary absl::nullopt_t object instead of using absl::nullopt
- // because absl::nullopt cannot be constexpr and have external linkage at the
- // same time.
- constexpr absl::optional<int> cempty{absl::nullopt_t(absl::nullopt_t::init)};
-#endif
static_assert(!cempty.has_value(), "");
EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>,
absl::nullopt_t>::value));
@@ -337,16 +339,18 @@ TEST(optionalTest, InPlaceConstructor) {
static_assert((*opt2).x == ConstexprType::kCtorInitializerList, "");
#endif
- // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...>
- // SFINAE is added to optional::optional(absl::in_place_t, Args&&...).
- // struct I {
- // I(absl::in_place_t);
- // };
+ EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ absl::in_place_t>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ const absl::in_place_t&>::value));
+ EXPECT_TRUE(
+ (std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ absl::in_place_t, absl::in_place_t>::value));
- // EXPECT_FALSE((std::is_constructible<absl::optional<I>,
- // absl::in_place_t>::value));
- // EXPECT_FALSE((std::is_constructible<absl::optional<I>, const
- // absl::in_place_t&>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+ absl::in_place_t>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+ absl::in_place_t&&>::value));
}
// template<U=T> optional(U&&);
@@ -1476,8 +1480,8 @@ TEST(optionalTest, MoveAssignRegression) {
TEST(optionalTest, ValueType) {
EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value));
- EXPECT_TRUE(
- (std::is_same<absl::optional<std::string>::value_type, std::string>::value));
+ EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type,
+ std::string>::value));
EXPECT_FALSE(
(std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value));
}
@@ -1504,18 +1508,19 @@ TEST(optionalTest, Hash) {
static_assert(is_hash_enabled_for<absl::optional<int>>::value, "");
static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, "");
+ static_assert(
+ absl::type_traits_internal::IsHashable<absl::optional<int>>::value, "");
+ static_assert(
+ absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value,
+ "");
+ absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>();
+ absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>();
-#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
- _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
- // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
- // static_assert to catch any user-defined type that doesn't provide a hash
- // specialization. So instantiating std::hash<absl::optional<T>> will result
- // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, "");
+ static_assert(!absl::type_traits_internal::IsHashable<
+ absl::optional<NonHashable>>::value,
+ "");
#endif
// libstdc++ std::optional is missing remove_const_t, i.e. it's using
@@ -1623,4 +1628,29 @@ TEST(optionalTest, AssignmentConstraints) {
EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
}
+#if !defined(__EMSCRIPTEN__)
+struct NestedClassBug {
+ struct Inner {
+ bool dummy = false;
+ };
+ absl::optional<Inner> value;
+};
+
+TEST(optionalTest, InPlaceTSFINAEBug) {
+ NestedClassBug b;
+ ((void)b);
+ using Inner = NestedClassBug::Inner;
+
+ EXPECT_TRUE((std::is_default_constructible<Inner>::value));
+ EXPECT_TRUE((std::is_constructible<Inner>::value));
+ EXPECT_TRUE(
+ (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value));
+
+ absl::optional<Inner> o(absl::in_place);
+ EXPECT_TRUE(o.has_value());
+ o.emplace();
+ EXPECT_TRUE(o.has_value());
+}
+#endif // !defined(__EMSCRIPTEN__)
+
} // namespace
diff --git a/absl/types/span.h b/absl/types/span.h
index 99b6765b..98c6cdc8 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -5,7 +5,7 @@
// 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
+// https://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,
@@ -60,115 +60,18 @@
#include <cstddef>
#include <initializer_list>
#include <iterator>
-#include <string>
#include <type_traits>
#include <utility>
-#include "absl/algorithm/algorithm.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
-#include "absl/base/port.h"
+#include "absl/base/port.h" // TODO(strel): remove this include
#include "absl/meta/type_traits.h"
+#include "absl/types/internal/span.h"
namespace absl {
-inline namespace lts_2018_12_18 {
-
-template <typename T>
-class Span;
-
-namespace span_internal {
-// A constexpr min function
-constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
-
-// Wrappers for access to container data pointers.
-template <typename C>
-constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
- -> decltype(c.data()) {
- return c.data();
-}
-
-// Before C++17, string::data returns a const char* in all cases.
-inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
- int) noexcept {
- return &s[0];
-}
-
-template <typename C>
-constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
- -> decltype(GetDataImpl(c, 0)) {
- return GetDataImpl(c, 0);
-}
-
-// Detection idioms for size() and data().
-template <typename C>
-using HasSize =
- std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
-
-// We want to enable conversion from vector<T*> to Span<const T* const> but
-// disable conversion from vector<Derived> to Span<Base>. Here we use
-// the fact that U** is convertible to Q* const* if and only if Q is the same
-// type or a more cv-qualified version of U. We also decay the result type of
-// data() to avoid problems with classes which have a member function data()
-// which returns a reference.
-template <typename T, typename C>
-using HasData =
- std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
- T* const*>;
-
-// Extracts value type from a Container
-template <typename C>
-struct ElementType {
- using type = typename absl::remove_reference_t<C>::value_type;
-};
-
-template <typename T, size_t N>
-struct ElementType<T (&)[N]> {
- using type = T;
-};
-
-template <typename C>
-using ElementT = typename ElementType<C>::type;
-
-template <typename T>
-using EnableIfMutable =
- typename std::enable_if<!std::is_const<T>::value, int>::type;
-
-template <typename T>
-bool EqualImpl(Span<T> a, Span<T> b) {
- static_assert(std::is_const<T>::value, "");
- return absl::equal(a.begin(), a.end(), b.begin(), b.end());
-}
-
-template <typename T>
-bool LessThanImpl(Span<T> a, Span<T> b) {
- static_assert(std::is_const<T>::value, "");
- return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
-}
-
-// The `IsConvertible` classes here are needed because of the
-// `std::is_convertible` bug in libcxx when compiled with GCC. This build
-// configuration is used by Android NDK toolchain. Reference link:
-// https://bugs.llvm.org/show_bug.cgi?id=27538.
-template <typename From, typename To>
-struct IsConvertibleHelper {
- private:
- static std::true_type testval(To);
- static std::false_type testval(...);
-
- public:
- using type = decltype(testval(std::declval<From>()));
-};
-
-template <typename From, typename To>
-struct IsConvertible : IsConvertibleHelper<From, To>::type {};
-
-// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
-// older version of libcxx is not supported.
-template <typename From, typename To>
-using EnableIfConvertibleToSpanConst =
- typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
-} // namespace span_internal
+inline namespace lts_2019_08_08 {
//------------------------------------------------------------------------------
// Span
@@ -486,6 +389,40 @@ class Span {
: (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
}
+ // Span::first()
+ //
+ // Returns a `Span` containing first `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).first(1); // {10}
+ // absl::MakeSpan(vec).first(3); // {10, 11, 12}
+ // absl::MakeSpan(vec).first(5); // throws std::out_of_range
+ constexpr Span first(size_type len) const {
+ return (len <= size())
+ ? Span(data(), len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
+ // Span::last()
+ //
+ // Returns a `Span` containing last `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).last(1); // {13}
+ // absl::MakeSpan(vec).last(3); // {11, 12, 13}
+ // absl::MakeSpan(vec).last(5); // throws std::out_of_range
+ constexpr Span last(size_type len) const {
+ return (len <= size())
+ ? Span(size() - len + data(), len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, Span v) {
@@ -518,25 +455,27 @@ const typename Span<T>::size_type Span<T>::npos;
// operator==
template <typename T>
bool operator==(Span<T> a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<const T> a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<T> a, Span<const T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(const U& a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(Span<T> a, const U& b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
// operator!=
@@ -552,13 +491,15 @@ template <typename T>
bool operator!=(Span<T> a, Span<const T> b) {
return !(a == b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(const U& a, Span<T> b) {
return !(a == b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(Span<T> a, const U& b) {
return !(a == b);
}
@@ -566,25 +507,27 @@ bool operator!=(Span<T> a, const U& b) {
// operator<
template <typename T>
bool operator<(Span<T> a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<const T> a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<T> a, Span<const T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(const U& a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(Span<T> a, const U& b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
// operator>
@@ -600,13 +543,15 @@ template <typename T>
bool operator>(Span<T> a, Span<const T> b) {
return b < a;
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(const U& a, Span<T> b) {
return b < a;
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(Span<T> a, const U& b) {
return b < a;
}
@@ -624,13 +569,15 @@ template <typename T>
bool operator<=(Span<T> a, Span<const T> b) {
return !(b < a);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(const U& a, Span<T> b) {
return !(b < a);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(Span<T> a, const U& b) {
return !(b < a);
}
@@ -648,13 +595,15 @@ template <typename T>
bool operator>=(Span<T> a, Span<const T> b) {
return !(a < b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(const U& a, Span<T> b) {
return !(a < b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(Span<T> a, const U& b) {
return !(a < b);
}
@@ -759,6 +708,6 @@ template <int&... ExplicitArgumentBarrier, typename T, size_t N>
constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
return Span<const T>(array, N);
}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TYPES_SPAN_H_
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index bd739ff2..9269f911 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -139,8 +139,10 @@ TEST(CharSpan, StringCtor) {
EXPECT_THAT(s_const_abc, SpanIs(abc));
EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));
- EXPECT_FALSE((std::is_constructible<absl::Span<const int>, std::string>::value));
- EXPECT_TRUE((std::is_convertible<std::string, absl::Span<const char>>::value));
+ EXPECT_FALSE(
+ (std::is_constructible<absl::Span<const int>, std::string>::value));
+ EXPECT_TRUE(
+ (std::is_convertible<std::string, absl::Span<const char>>::value));
}
TEST(IntSpan, FromConstPointer) {
@@ -293,6 +295,38 @@ TEST(IntSpan, Subspan) {
#endif
}
+TEST(IntSpan, First) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), "");
+#endif
+}
+
+TEST(IntSpan, Last) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), "");
+#endif
+}
+
TEST(IntSpan, MakeSpanPtrLength) {
std::vector<int> empty;
auto s_empty = absl::MakeSpan(empty.data(), empty.size());
@@ -767,6 +801,8 @@ TEST(ConstIntSpan, ConstexprTest) {
ABSL_TEST_CONSTEXPR(span.begin());
ABSL_TEST_CONSTEXPR(span.cbegin());
ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
+ ABSL_TEST_CONSTEXPR(span.first(1));
+ ABSL_TEST_CONSTEXPR(span.last(1));
ABSL_TEST_CONSTEXPR(span[0]);
}
@@ -779,4 +815,19 @@ TEST(Span, SpanSize) {
EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));
}
+TEST(Span, Hash) {
+ int array[] = {1, 2, 3, 4};
+ int array2[] = {1, 2, 3};
+ using T = absl::Span<const int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ {// Empties
+ T(), T(nullptr, 0), T(array, 0), T(array2, 0),
+ // Different array with same value
+ T(array, 3), T(array2), T({1, 2, 3}),
+ // Same array, but different length
+ T(array, 1), T(array, 2),
+ // Same length, but different array
+ T(array + 1, 2), T(array + 2, 2)}));
+}
+
} // namespace
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 4ae4e00d..1c1962b1 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -47,10 +47,10 @@
#ifdef ABSL_HAVE_STD_VARIANT
-#include <variant>
+#include <variant> // IWYU pragma: export
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
using std::bad_variant_access;
using std::get;
using std::get_if;
@@ -63,7 +63,7 @@ using std::variant_npos;
using std::variant_size;
using std::variant_size_v;
using std::visit;
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#else // ABSL_HAVE_STD_VARIANT
@@ -79,7 +79,7 @@ using std::visit;
#include "absl/types/internal/variant.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
// -----------------------------------------------------------------------------
// absl::variant
@@ -132,7 +132,12 @@ class variant;
// type (in which case, they will be swapped) or to two different types (in
// which case the values will need to be moved).
//
-template <typename... Ts>
+template <
+ typename... Ts,
+ absl::enable_if_t<
+ absl::conjunction<std::is_move_constructible<Ts>...,
+ type_traits_internal::IsSwappable<Ts>...>::value,
+ int> = 0>
void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
v.swap(w);
}
@@ -691,12 +696,12 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
//
// Swaps the values of two variant objects.
//
- // TODO(calabrese)
- // `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
- // which is introduced in C++17. So we assume `is_swappable()` is always
- // true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
void swap(variant& rhs) noexcept(
- absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+ absl::conjunction<
+ std::is_nothrow_move_constructible<T0>,
+ std::is_nothrow_move_constructible<Tn>...,
+ type_traits_internal::IsNothrowSwappable<T0>,
+ type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
}
@@ -793,7 +798,7 @@ operator>=(const variant<Types...>& a, const variant<Types...>& b) {
a.index());
}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
namespace std {
@@ -814,7 +819,7 @@ struct hash<absl::variant<T...>>
#endif // ABSL_HAVE_STD_VARIANT
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace variant_internal {
// Helper visitor for converting a variant<Ts...>` into another type (mostly
@@ -850,7 +855,7 @@ To ConvertVariantTo(Variant&& variant) {
std::forward<Variant>(variant));
}
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // ABSL_TYPES_VARIANT_H_
diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc
index 854f1448..efe02310 100644
--- a/absl/types/variant_benchmark.cc
+++ b/absl/types/variant_benchmark.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -28,7 +28,7 @@
#include "absl/utility/utility.h"
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace {
template <std::size_t I>
@@ -218,5 +218,5 @@ BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2)
->DenseRange(0, integral_pow(4, 2) - 1);
} // namespace
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
index ff166051..31662545 100644
--- a/absl/types/variant_exception_safety_test.cc
+++ b/absl/types/variant_exception_safety_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -24,11 +24,12 @@
#include "absl/base/config.h"
#include "absl/base/internal/exception_safety_testing.h"
#include "absl/memory/memory.h"
+
// See comment in absl/base/config.h
#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace {
using ::testing::MakeExceptionSafetyTester;
@@ -316,6 +317,12 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
}
{
+ // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
+ // The fix is targeted for gcc-9.
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
+ // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
+#if !(defined(ABSL_HAVE_STD_VARIANT) && \
+ defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
// - otherwise (index() != j), equivalent to
// emplace<j>(get<j>(std::move(rhs)))
// - If an exception is thrown during the call to Tj's move construction
@@ -331,6 +338,8 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
auto copy = rhs;
*lhs = std::move(copy);
}));
+#endif // !(defined(ABSL_HAVE_STD_VARIANT) &&
+ // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
}
}
@@ -510,7 +519,7 @@ TEST(VariantExceptionSafetyTest, Swap) {
}
} // namespace
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl
#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index 59223ea7..ff0f187a 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -4,7 +4,7 @@
// 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
+// https://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,
@@ -67,7 +67,7 @@ struct hash<Hashable> {
struct NonHashable {};
namespace absl {
-inline namespace lts_2018_12_18 {
+inline namespace lts_2019_08_08 {
namespace {
using ::testing::DoubleEq;
@@ -258,7 +258,7 @@ class NonCopyable {
// each type.
template <typename T>
class VariantTypesTest : public ::testing::Test {};
-TYPED_TEST_CASE(VariantTypesTest, VariantTypes);
+TYPED_TEST_SUITE(VariantTypesTest, VariantTypes);
////////////////////
// [variant.ctor] //
@@ -385,7 +385,7 @@ struct MoveOnly {
TEST(VariantTest, TestMoveConstruct) {
using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>;
- V v(in_place_index_t<1>{}, 10);
+ V v(in_place_index<1>, 10);
V v2 = absl::move(v);
EXPECT_EQ(10, absl::get<1>(v2).value);
}
@@ -461,6 +461,11 @@ TYPED_TEST(VariantTypesTest, TestValueCtor) {
EXPECT_EQ(value.value, mutable_valptr->value);
}
+TEST(VariantTest, AmbiguousValueConstructor) {
+ EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value));
+ EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value));
+}
+
TEST(VariantTest, InPlaceType) {
using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
@@ -484,14 +489,47 @@ TEST(VariantTest, InPlaceType) {
EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
}
+TEST(VariantTest, InPlaceTypeVariableTemplate) {
+ using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+ Var v1(in_place_type<int>, 7);
+ ASSERT_TRUE(absl::holds_alternative<int>(v1));
+ EXPECT_EQ(7, absl::get<int>(v1));
+
+ Var v2(in_place_type<std::string>, "ABC");
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+ EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+ Var v3(in_place_type<std::string>, "ABC", 2);
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+ EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+ Var v4(in_place_type<NonCopyable>);
+ ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+ Var v5(in_place_type<std::vector<int>>, {1, 2, 3});
+ ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+ EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
TEST(VariantTest, InPlaceTypeInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
}
+TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) {
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+ Var v1(in_place_type<MoveOnlyWithListConstructor>, {1, 2, 3, 4, 5}, 6);
+ ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+ EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
TEST(VariantTest, InPlaceIndex) {
using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
@@ -519,14 +557,51 @@ TEST(VariantTest, InPlaceIndex) {
EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
}
+TEST(VariantTest, InPlaceIndexVariableTemplate) {
+ using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+ Var v1(in_place_index<0>, 7);
+ ASSERT_TRUE(absl::holds_alternative<int>(v1));
+ EXPECT_EQ(7, absl::get<int>(v1));
+
+ Var v2(in_place_index<1>, "ABC");
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+ EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+ Var v3(in_place_index<1>, "ABC", 2);
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+ EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+ Var v4(in_place_index<2>);
+ EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+ // Verify that a variant with only non-copyables can still be constructed.
+ EXPECT_TRUE(absl::holds_alternative<NonCopyable>(
+ variant<NonCopyable>(in_place_index<0>)));
+
+ Var v5(in_place_index<3>, {1, 2, 3});
+ ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+ EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
TEST(VariantTest, InPlaceIndexInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
}
+TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) {
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+ Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6);
+ ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+ EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
////////////////////
// [variant.dtor] //
////////////////////
@@ -560,6 +635,7 @@ TEST(VariantTest, TestDtor) {
}
#ifdef ABSL_HAVE_EXCEPTIONS
+
// See comment in absl/base/config.h
#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
TEST(VariantTest, DISABLED_TestDtorValuelessByException)
@@ -574,7 +650,7 @@ TEST(VariantTest, TestDtorValuelessByException)
{
using Variant = VariantFactory<IncrementInDtor>::Type;
- Variant v(in_place_index_t<0>(), counter_adjuster);
+ Variant v(in_place_index<0>, counter_adjuster);
EXPECT_EQ(0, counter);
ToValuelessByException(v);
@@ -808,7 +884,7 @@ TEST(VariantTest, TestBackupAssign) {
TEST(VariantTest, TestEmplaceBasic) {
using Variant = variant<int, char>;
- Variant v(absl::in_place_index_t<0>{}, 0);
+ Variant v(absl::in_place_index<0>, 0);
{
char& emplace_result = v.emplace<char>();
@@ -832,9 +908,10 @@ TEST(VariantTest, TestEmplaceBasic) {
}
TEST(VariantTest, TestEmplaceInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
- Var v1(absl::in_place_index_t<0>{}, 555);
+ Var v1(absl::in_place_index<0>, 555);
MoveOnlyWithListConstructor& emplace_result =
v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -845,7 +922,7 @@ TEST(VariantTest, TestEmplaceInitializerList) {
TEST(VariantTest, TestEmplaceIndex) {
using Variant = variant<int, char>;
- Variant v(absl::in_place_index_t<0>{}, 555);
+ Variant v(absl::in_place_index<0>, 555);
{
char& emplace_result = v.emplace<1>();
@@ -869,9 +946,10 @@ TEST(VariantTest, TestEmplaceIndex) {
}
TEST(VariantTest, TestEmplaceIndexInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
- Var v1(absl::in_place_index_t<0>{}, 555);
+ Var v1(absl::in_place_index<0>, 555);
MoveOnlyWithListConstructor& emplace_result =
v1.emplace<3>({1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -920,7 +998,7 @@ TEST(VariantTest, NotValuelessByException) {
TEST(VariantTest, IndexValuelessByException) {
using Var = variant<MoveCanThrow, std::string, double>;
- Var v(absl::in_place_index_t<0>{});
+ Var v(absl::in_place_index<0>);
EXPECT_EQ(0, v.index());
ToValuelessByException(v);
EXPECT_EQ(absl::variant_npos, v.index());
@@ -931,7 +1009,7 @@ TEST(VariantTest, IndexValuelessByException) {
TEST(VariantTest, ValuelessByException) {
using Var = variant<MoveCanThrow, std::string, double>;
- Var v(absl::in_place_index_t<0>{});
+ Var v(absl::in_place_index<0>);
EXPECT_FALSE(v.valueless_by_exception());
ToValuelessByException(v);
EXPECT_TRUE(v.valueless_by_exception());
@@ -962,7 +1040,7 @@ TEST(VariantTest, MemberSwap) {
using V = variant<MoveCanThrow, std::string, int>;
int i = 33;
std::string s = "abc";
- V valueless(in_place_index_t<0>{});
+ V valueless(in_place_index<0>);
ToValuelessByException(valueless);
{
// lhs and rhs holds different alternative
@@ -1123,7 +1201,7 @@ TEST(VariantTest, GetIndex) {
using Var = variant<int, std::string, double, int>;
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
using LValueGetType = decltype(absl::get<0>(v));
using RValueGetType = decltype(absl::get<0>(absl::move(v)));
@@ -1183,7 +1261,7 @@ TEST(VariantTest, GetIndex) {
}
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
v.emplace<3>(1);
using LValueGetType = decltype(absl::get<3>(v));
@@ -1307,7 +1385,8 @@ TEST(VariantTest, BadGetType) {
absl::get<std::string>(std::move(v)));
const Var& const_v = v;
- ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(const_v));
+ ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+ absl::get<std::string>(const_v));
ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
absl::get<std::string>(std::move(const_v))); // NOLINT
}
@@ -1329,7 +1408,7 @@ TEST(VariantTest, GetIfIndex) {
using Var = variant<int, std::string, double, int>;
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
EXPECT_TRUE(noexcept(absl::get_if<0>(&v)));
{
@@ -1364,7 +1443,8 @@ TEST(VariantTest, GetIfIndex) {
EXPECT_EQ(*elem, 0);
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1473,7 +1553,8 @@ TEST(VariantTest, GetIfIndex) {
}
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1485,7 +1566,7 @@ TEST(VariantTest, GetIfIndex) {
}
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
v.emplace<3>(1);
EXPECT_TRUE(noexcept(absl::get_if<3>(&v)));
@@ -1526,7 +1607,8 @@ TEST(VariantTest, GetIfIndex) {
}
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1630,8 +1712,8 @@ TEST(VariantTest, OperatorRelational) {
TEST(VariantTest, ValuelessOperatorEquals) {
variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
- valueless(absl::in_place_index_t<0>{}),
- other_valueless(absl::in_place_index_t<0>{});
+ valueless(absl::in_place_index<0>),
+ other_valueless(absl::in_place_index<0>);
ToValuelessByException(valueless);
ToValuelessByException(other_valueless);
@@ -1652,8 +1734,8 @@ TEST(VariantTest, ValuelessOperatorEquals) {
TEST(VariantTest, ValuelessOperatorRelational) {
variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
- valueless(absl::in_place_index_t<0>{}),
- other_valueless(absl::in_place_index_t<0>{});
+ valueless(absl::in_place_index<0>),
+ other_valueless(absl::in_place_index<0>);
ToValuelessByException(valueless);
ToValuelessByException(other_valueless);
@@ -1712,8 +1794,8 @@ TEST(VariantTest, VisitSimple) {
EXPECT_EQ("B", piece);
struct StrLen {
- int operator()(const std::string& s) const { return s.size(); }
int operator()(const char* s) const { return strlen(s); }
+ int operator()(const std::string& s) const { return s.size(); }
};
v = "SomeStr";
@@ -1729,9 +1811,13 @@ TEST(VariantTest, VisitRValue) {
bool operator()(std::string&&) const { return true; } // NOLINT
int operator()(const std::string&, const std::string&) const { return 0; }
- int operator()(const std::string&, std::string&&) const { return 1; } // NOLINT
- int operator()(std::string&&, const std::string&) const { return 2; } // NOLINT
- int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT
+ int operator()(const std::string&, std::string&&) const {
+ return 1;
+ } // NOLINT
+ int operator()(std::string&&, const std::string&) const {
+ return 2;
+ } // NOLINT
+ int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT
};
EXPECT_FALSE(absl::visit(Visitor{}, v));
EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v)));
@@ -1807,9 +1893,9 @@ TEST(VariantTest, VisitVariadic) {
EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
B(std::unique_ptr<int>(new int(7)))),
::testing::Pair(5, 7));
- EXPECT_THAT(
- absl::visit(Visitor(), A(std::string("BBBBB")), B(absl::string_view("ABC"))),
- ::testing::Pair(5, 3));
+ EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
+ B(absl::string_view("ABC"))),
+ ::testing::Pair(5, 3));
}
TEST(VariantTest, VisitNoArgs) {
@@ -1978,29 +2064,17 @@ TEST(VariantTest, MonostateHash) {
}
TEST(VariantTest, Hash) {
- static_assert(type_traits_internal::IsHashEnabled<variant<int>>::value, "");
- static_assert(type_traits_internal::IsHashEnabled<variant<Hashable>>::value,
+ static_assert(type_traits_internal::IsHashable<variant<int>>::value, "");
+ static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
+ static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
"");
- static_assert(
- type_traits_internal::IsHashEnabled<variant<int, Hashable>>::value, "");
-
-#if defined(_MSC_VER) || \
- (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 && \
- _LIBCPP_STD_VER > 11) || \
- defined(__APPLE__)
- // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
- // static_assert to catch any user-defined type T that doesn't provide a hash
- // specialization. So instantiating std::hash<variant<T>> will result
- // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
- static_assert(
- !type_traits_internal::IsHashEnabled<variant<NonHashable>>::value, "");
- static_assert(!type_traits_internal::IsHashEnabled<
- variant<Hashable, NonHashable>>::value,
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+ static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
"");
+ static_assert(
+ !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value,
+ "");
#endif
// MSVC std::hash<std::variant> does not use the index, thus produce the same
@@ -2008,8 +2082,8 @@ TEST(VariantTest, Hash) {
#if !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
{
// same value as different alternative
- variant<int, int> v0(in_place_index_t<0>{}, 42);
- variant<int, int> v1(in_place_index_t<1>{}, 42);
+ variant<int, int> v0(in_place_index<0>, 42);
+ variant<int, int> v1(in_place_index<1>, 42);
std::hash<variant<int, int>> hash;
EXPECT_NE(hash(v0), hash(v1));
}
@@ -2024,11 +2098,10 @@ TEST(VariantTest, Hash) {
EXPECT_GT(hashcodes.size(), 90);
// test const-qualified
+ static_assert(type_traits_internal::IsHashable<variant<const int>>::value,
+ "");
static_assert(
- type_traits_internal::IsHashEnabled<variant<const int>>::value, "");
- static_assert(
- type_traits_internal::IsHashEnabled<variant<const Hashable>>::value,
- "");
+ type_traits_internal::IsHashable<variant<const Hashable>>::value, "");
std::hash<absl::variant<const int>> c_hash;
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(hash(i), c_hash(i));
@@ -2040,7 +2113,8 @@ TEST(VariantTest, Hash) {
// Miscellaneous and deprecated tests //
////////////////////////////////////////
-// Test that a set requiring a basic type conversion works correctly.
+// Test that a set requiring a basic type conversion works correctly
+#if !defined(ABSL_HAVE_STD_VARIANT)
TEST(VariantTest, TestConvertingSet) {
typedef variant<double> Variant;
Variant v(1.0);
@@ -2050,6 +2124,7 @@ TEST(VariantTest, TestConvertingSet) {
ASSERT_TRUE(nullptr != absl::get_if<double>(&v));
EXPECT_DOUBLE_EQ(2, absl::get<double>(v));
}
+#endif // ABSL_HAVE_STD_VARIANT
// Test that a vector of variants behaves reasonably.
TEST(VariantTest, Container) {
@@ -2177,7 +2252,8 @@ TEST(VariantTest, TestImplicitConversion) {
// We still need the explicit cast for std::string, because C++ won't apply
// two user-defined implicit conversions in a row.
- EXPECT_TRUE(absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
+ EXPECT_TRUE(
+ absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
}
struct Convertible2;
@@ -2200,8 +2276,10 @@ struct Convertible2 {
};
TEST(VariantTest, TestRvalueConversion) {
+#if !defined(ABSL_HAVE_STD_VARIANT)
variant<double, std::string> var(
- ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(0)));
+ ConvertVariantTo<variant<double, std::string>>(
+ variant<std::string, int>(0)));
ASSERT_TRUE(absl::holds_alternative<double>(var));
EXPECT_EQ(0.0, absl::get<double>(var));
@@ -2231,6 +2309,7 @@ TEST(VariantTest, TestRvalueConversion) {
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+#endif // !ABSL_HAVE_STD_VARIANT
variant<Convertible1, Convertible2> variant3(
ConvertVariantTo<variant<Convertible1, Convertible2>>(
@@ -2243,6 +2322,7 @@ TEST(VariantTest, TestRvalueConversion) {
}
TEST(VariantTest, TestLvalueConversion) {
+#if !defined(ABSL_HAVE_STD_VARIANT)
variant<std::string, int> source1 = 0;
variant<double, std::string> destination(
ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2279,6 +2359,7 @@ TEST(VariantTest, TestLvalueConversion) {
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+#endif
variant<Convertible2, Convertible1> source7((Convertible1()));
variant<Convertible1, Convertible2> variant3(
@@ -2293,7 +2374,8 @@ TEST(VariantTest, TestLvalueConversion) {
TEST(VariantTest, TestMoveConversion) {
using Variant =
variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
- using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
Variant var(
ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
@@ -2301,8 +2383,8 @@ TEST(VariantTest, TestMoveConversion) {
ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
- var =
- ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+ var = ConvertVariantTo<Variant>(
+ OtherVariant(absl::make_unique<std::string>("foo")));
ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
}
@@ -2313,7 +2395,8 @@ TEST(VariantTest, DoesNotMoveFromLvalues) {
// whether moving or copying has occurred.
using Variant =
variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
- using OtherVariant = variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
Variant v1(std::make_shared<const int>(0));
@@ -2341,8 +2424,10 @@ TEST(VariantTest, DoesNotMoveFromLvalues) {
}
TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
+#if !defined(ABSL_HAVE_STD_VARIANT)
variant<double, std::string> var(
- ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(3)));
+ ConvertVariantTo<variant<double, std::string>>(
+ variant<std::string, int>(3)));
EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
var = ConvertVariantTo<variant<double, std::string>>(
@@ -2365,6 +2450,7 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+#endif
variant<Convertible1, Convertible2> variant3(
ConvertVariantTo<variant<Convertible1, Convertible2>>(
@@ -2377,6 +2463,7 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
}
TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
+#if !defined(ABSL_HAVE_STD_VARIANT)
variant<std::string, int> source1 = 3;
variant<double, std::string> destination(
ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2384,7 +2471,8 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
variant<const char*, float> source2 = "foo";
destination = ConvertVariantTo<variant<double, std::string>>(source2);
- EXPECT_THAT(absl::get_if<std::string>(&destination), Pointee(std::string("foo")));
+ EXPECT_THAT(absl::get_if<std::string>(&destination),
+ Pointee(std::string("foo")));
variant<int, float> source3(42);
variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
@@ -2407,6 +2495,7 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
variant<uint32_t> source6(42);
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+#endif // !ABSL_HAVE_STD_VARIANT
variant<Convertible2, Convertible1> source7((Convertible1()));
variant<Convertible1, Convertible2> variant3(
@@ -2421,15 +2510,16 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
using Variant =
variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
- using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
Variant var(
ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
Pointee(Pointee(3)));
- var =
- ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+ var = ConvertVariantTo<Variant>(
+ OtherVariant(absl::make_unique<std::string>("foo")));
EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
Pointee(Pointee(std::string("foo"))));
}
@@ -2599,7 +2689,7 @@ TEST(VariantTest, MoveCtorBug) {
};
{
using V = absl::variant<TrivialCopyNontrivialMove, int>;
- V v1(absl::in_place_index_t<0>{});
+ V v1(absl::in_place_index<0>);
// this should invoke the move ctor, rather than the trivial copy ctor.
V v2(std::move(v1));
EXPECT_TRUE(absl::get<0>(v2).called);
@@ -2607,7 +2697,7 @@ TEST(VariantTest, MoveCtorBug) {
{
// this case failed to compile before our fix due to a GCC bug.
using V = absl::variant<int, TrivialCopyNontrivialMove>;
- V v1(absl::in_place_index_t<1>{});
+ V v1(absl::in_place_index<1>);
// this should invoke the move ctor, rather than the trivial copy ctor.
V v2(std::move(v1));
EXPECT_TRUE(absl::get<1>(v2).called);
@@ -2615,5 +2705,5 @@ TEST(VariantTest, MoveCtorBug) {
}
} // namespace
-} // inline namespace lts_2018_12_18
+} // inline namespace lts_2019_08_08
} // namespace absl