diff options
author | Zie Weaver <zearen@google.com> | 2023-10-18 16:17:51 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-10-18 16:18:51 -0700 |
commit | 9687a8ea750bfcddf790372093245a1d041b21a3 (patch) | |
tree | 32c06ea4c2061d0212872cc37b73ce487b1af84c /absl/strings | |
parent | 7676c565eedd2581b66839c239f3825d8e381119 (diff) |
Add a template gadget to detect whether a type supports the ostream operator.
I.e. for a type `Example`, if
```
std::ostream& operator<<(std::ostream&, const Example&);
```
is declared, `absl::HasOstreamOperator<Example>::value` is `true`.
PiperOrigin-RevId: 574637891
Change-Id: I123d8f35a6e3ea894745133f7d81b1610fb475d5
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/BUILD.bazel | 25 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 26 | ||||
-rw-r--r-- | absl/strings/has_absl_stringify_test.cc | 3 | ||||
-rw-r--r-- | absl/strings/has_ostream_operator.h | 42 | ||||
-rw-r--r-- | absl/strings/has_ostream_operator_test.cc | 41 |
5 files changed, 137 insertions, 0 deletions
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 37273491..a3ef3ae8 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -194,6 +194,31 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/types:optional", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( + name = "has_ostream_operator", + hdrs = ["has_ostream_operator.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + ], +) + +cc_test( + name = "has_ostream_operator_test", + size = "small", + srcs = ["has_ostream_operator_test.cc"], + copts = ABSL_TEST_COPTS, + visibility = ["//visibility:private"], + deps = [ + ":has_ostream_operator", + "//absl/types:optional", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index f470ff5a..b129096d 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -103,6 +103,18 @@ absl_cc_library( PUBLIC ) +absl_cc_library( + NAME + has_ostream_operator + HDRS + "has_ostream_operator.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + PUBLIC +) + # Internal-only target, do not depend on directly. absl_cc_library( NAME @@ -162,12 +174,26 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS + absl::optional absl::strings GTest::gmock_main ) absl_cc_test( NAME + has_ostream_operator_test + SRCS + "has_ostream_operator_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::has_ostream_operator + absl::optional + GTest::gmock_main +) + +absl_cc_test( + NAME ascii_test SRCS "ascii_test.cc" diff --git a/absl/strings/has_absl_stringify_test.cc b/absl/strings/has_absl_stringify_test.cc index e9915c66..59e7e1d3 100644 --- a/absl/strings/has_absl_stringify_test.cc +++ b/absl/strings/has_absl_stringify_test.cc @@ -17,6 +17,7 @@ #include <string> #include "gtest/gtest.h" +#include "absl/types/optional.h" namespace { @@ -32,6 +33,8 @@ TEST(HasAbslStringifyTest, Works) { EXPECT_FALSE(absl::HasAbslStringify<std::string>::value); EXPECT_FALSE(absl::HasAbslStringify<TypeWithoutAbslStringify>::value); EXPECT_TRUE(absl::HasAbslStringify<TypeWithAbslStringify>::value); + EXPECT_FALSE( + absl::HasAbslStringify<absl::optional<TypeWithAbslStringify>>::value); } } // namespace diff --git a/absl/strings/has_ostream_operator.h b/absl/strings/has_ostream_operator.h new file mode 100644 index 00000000..156ffc74 --- /dev/null +++ b/absl/strings/has_ostream_operator.h @@ -0,0 +1,42 @@ +// Copyright 2023 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_STRINGS_HAS_OSTREAM_OPERATOR_H_ +#define ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_ + +#include <ostream> +#include <type_traits> +#include <utility> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// Detects if type `T` supports streaming to `std::ostream`s with `operator<<`. + +template <typename T, typename = void> +struct HasOstreamOperator : std::false_type {}; + +template <typename T> +struct HasOstreamOperator< + T, std::enable_if_t<std::is_same< + std::ostream&, decltype(std::declval<std::ostream&>() + << std::declval<const T&>())>::value>> + : std::true_type {}; + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_STRINGS_HAS_OSTREAM_OPERATOR_H_ diff --git a/absl/strings/has_ostream_operator_test.cc b/absl/strings/has_ostream_operator_test.cc new file mode 100644 index 00000000..9ef41366 --- /dev/null +++ b/absl/strings/has_ostream_operator_test.cc @@ -0,0 +1,41 @@ +// Copyright 2023 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/strings/has_ostream_operator.h" + +#include <ostream> +#include <string> + +#include "gtest/gtest.h" +#include "absl/types/optional.h" + +namespace { + +struct TypeWithoutOstreamOp {}; + +struct TypeWithOstreamOp { + friend std::ostream& operator<<(std::ostream& os, const TypeWithOstreamOp&) { + return os; + } +}; + +TEST(HasOstreamOperatorTest, Works) { + EXPECT_TRUE(absl::HasOstreamOperator<int>::value); + EXPECT_TRUE(absl::HasOstreamOperator<std::string>::value); + EXPECT_FALSE(absl::HasOstreamOperator<absl::optional<int>>::value); + EXPECT_FALSE(absl::HasOstreamOperator<TypeWithoutOstreamOp>::value); + EXPECT_TRUE(absl::HasOstreamOperator<TypeWithOstreamOp>::value); +} + +} // namespace |