// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/template_util.h" #include #include #include "base/containers/flat_tree.h" #include "base/test/move_only_int.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace { enum SimpleEnum { SIMPLE_ENUM }; enum EnumWithExplicitType : uint64_t { ENUM_WITH_EXPLICIT_TYPE }; enum class ScopedEnum { SCOPED_ENUM }; enum class ScopedEnumWithOperator { SCOPED_ENUM_WITH_OPERATOR }; std::ostream& operator<<(std::ostream& os, ScopedEnumWithOperator v) { return os; } struct SimpleStruct {}; struct StructWithOperator {}; std::ostream& operator<<(std::ostream& os, const StructWithOperator& v) { return os; } struct StructWithToString { std::string ToString() const { return ""; } }; // is_non_const_reference static_assert(!is_non_const_reference::value, "IsNonConstReference"); static_assert(!is_non_const_reference::value, "IsNonConstReference"); static_assert(is_non_const_reference::value, "IsNonConstReference"); // A few standard types that definitely support printing. static_assert(internal::SupportsOstreamOperator::value, "ints should be printable"); static_assert(internal::SupportsOstreamOperator::value, "C strings should be printable"); static_assert(internal::SupportsOstreamOperator::value, "std::string should be printable"); // Various kinds of enums operator<< support. static_assert(internal::SupportsOstreamOperator::value, "simple enum should be printable by value"); static_assert(internal::SupportsOstreamOperator::value, "simple enum should be printable by const ref"); static_assert(internal::SupportsOstreamOperator::value, "enum with explicit type should be printable by value"); static_assert( internal::SupportsOstreamOperator::value, "enum with explicit type should be printable by const ref"); static_assert(!internal::SupportsOstreamOperator::value, "scoped enum should not be printable by value"); static_assert(!internal::SupportsOstreamOperator::value, "simple enum should not be printable by const ref"); static_assert(internal::SupportsOstreamOperator::value, "scoped enum with operator<< should be printable by value"); static_assert( internal::SupportsOstreamOperator::value, "scoped enum with operator<< should be printable by const ref"); // operator<< support on structs. static_assert(!internal::SupportsOstreamOperator::value, "simple struct should not be printable by value"); static_assert(!internal::SupportsOstreamOperator::value, "simple struct should not be printable by const ref"); static_assert(internal::SupportsOstreamOperator::value, "struct with operator<< should be printable by value"); static_assert( internal::SupportsOstreamOperator::value, "struct with operator<< should be printable by const ref"); // .ToString() support on structs. static_assert(!internal::SupportsToString::value, "simple struct value doesn't support .ToString()"); static_assert(!internal::SupportsToString::value, "simple struct const ref doesn't support .ToString()"); static_assert(internal::SupportsToString::value, "struct with .ToString() should be printable by value"); static_assert(internal::SupportsToString::value, "struct with .ToString() should be printable by const ref"); // base::is_trivially_copyable class TrivialCopy { public: TrivialCopy(int d) : data_(d) {} protected: int data_; }; class TrivialCopyButWithDestructor : public TrivialCopy { public: TrivialCopyButWithDestructor(int d) : TrivialCopy(d) {} ~TrivialCopyButWithDestructor() { data_ = 0; } }; static_assert(base::is_trivially_copyable::value, "TrivialCopy should be detected as trivially copyable"); static_assert(!base::is_trivially_copyable::value, "TrivialCopyButWithDestructor should not be detected as " "trivially copyable"); class NoCopy { public: NoCopy(const NoCopy&) = delete; }; static_assert( !base::is_trivially_copy_constructible>::value, "is_trivially_copy_constructible> must be compiled."); using TrueT = std::true_type; using FalseT = std::false_type; // bool_constant static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); struct True { static constexpr bool value = true; }; struct False { static constexpr bool value = false; }; // conjunction static_assert(conjunction<>::value, ""); static_assert(conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(!conjunction::value, ""); static_assert(conjunction::value, ""); static_assert(!conjunction::value, ""); // disjunction static_assert(!disjunction<>::value, ""); static_assert(disjunction::value, ""); static_assert(!disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(!disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(!disjunction::value, ""); static_assert(disjunction::value, ""); static_assert(!disjunction::value, ""); // negation static_assert(!negation::value, ""); static_assert(negation::value, ""); static_assert(!negation::value, ""); static_assert(negation::value, ""); static_assert(negation>::value, ""); static_assert(!negation>::value, ""); // is_invocable TEST(TemplateUtil, IsInvocable) { struct Base {}; struct Derived : Base {}; struct Implicit { Implicit(int) {} }; struct Explicit { explicit Explicit(int) {} }; struct CallableWithBaseButNotWithInt { int operator()(int) = delete; int operator()(Base) { return 42; } }; { using Fp = void (*)(Base&, int); static_assert(is_invocable::value, ""); static_assert(is_invocable::value, ""); static_assert(!is_invocable::value, ""); static_assert(!is_invocable::value, ""); static_assert(!is_invocable::value, ""); } { // Function reference using Fp = void (&)(Base&, int); static_assert(is_invocable::value, ""); static_assert(is_invocable::value, ""); static_assert(!is_invocable::value, ""); static_assert(!is_invocable::value, ""); static_assert(!is_invocable::value, ""); } { // Function object using Fn = CallableWithBaseButNotWithInt; static_assert(is_invocable::value, ""); static_assert(!is_invocable::value, ""); } { // Check that the conversion to the return type is properly checked using Fn = int (*)(int); static_assert(is_invocable_r::value, ""); static_assert(is_invocable_r::value, ""); static_assert(is_invocable_r::value, ""); static_assert(!is_invocable_r::value, ""); static_assert(is_invocable_r::value, ""); static_assert(!is_invocable_r::value, ""); static_assert(is_invocable_r::value, ""); static_assert(!is_invocable_r::value, ""); } } // is_scoped_enum TEST(TemplateUtil, IsScopedEnum) { static_assert(!is_scoped_enum::value, ""); static_assert(!is_scoped_enum::value, ""); static_assert(!is_scoped_enum::value, ""); static_assert(is_scoped_enum::value, ""); } TEST(TemplateUtil, RemoveCvRefT) { static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert( std::is_same>::value, ""); static_assert(std::is_same>::value, ""); // Test references and pointers to arrays. static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); // Test references and pointers to functions. static_assert(std::is_same>::value, ""); static_assert(std::is_same>::value, ""); static_assert( std::is_same>::value, ""); } TEST(TemplateUtil, IsConstantEvaluated) { // base::is_constant_evaluated() should return whether it is evaluated as part // of a constant expression. static_assert(is_constant_evaluated(), ""); EXPECT_FALSE(is_constant_evaluated()); } } // namespace } // namespace base