// Copyright 2017 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/utility/utility.h" #include #include #include #include #include #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/attributes.h" namespace { #ifdef _MSC_VER // Warnings for unused variables in this test are false positives. On other // platforms, they are suppressed by ABSL_ATTRIBUTE_UNUSED, but that doesn't // work on MSVC. // Both the unused variables and the name length warnings are due to calls // to absl::make_index_sequence with very large values, creating very long type // names. The resulting warnings are so long they make build output unreadable. #pragma warning( push ) #pragma warning( disable : 4503 ) // decorated name length exceeded #pragma warning( disable : 4101 ) // unreferenced local variable #endif // _MSC_VER using testing::StaticAssertTypeEq; using testing::ElementsAre; TEST(IntegerSequenceTest, ValueType) { StaticAssertTypeEq::value_type>(); StaticAssertTypeEq::value_type>(); } TEST(IntegerSequenceTest, Size) { EXPECT_EQ(0, (absl::integer_sequence::size())); EXPECT_EQ(1, (absl::integer_sequence::size())); EXPECT_EQ(1, (absl::integer_sequence::size())); EXPECT_EQ(2, (absl::integer_sequence::size())); EXPECT_EQ(3, (absl::integer_sequence::size())); EXPECT_EQ(3, (absl::integer_sequence::size())); constexpr size_t sz = absl::integer_sequence::size(); EXPECT_EQ(2, sz); } TEST(IntegerSequenceTest, MakeIndexSequence) { StaticAssertTypeEq, absl::make_index_sequence<0>>(); StaticAssertTypeEq, absl::make_index_sequence<1>>(); StaticAssertTypeEq, absl::make_index_sequence<2>>(); StaticAssertTypeEq, absl::make_index_sequence<3>>(); } TEST(IntegerSequenceTest, MakeIntegerSequence) { StaticAssertTypeEq, absl::make_integer_sequence>(); StaticAssertTypeEq, absl::make_integer_sequence>(); StaticAssertTypeEq, absl::make_integer_sequence>(); StaticAssertTypeEq, absl::make_integer_sequence>(); } template class Counter {}; template void CountAll(absl::index_sequence) { // We only need an alias here, but instantiate a variable to silence warnings // for unused typedefs in some compilers. ABSL_ATTRIBUTE_UNUSED Counter...> seq; } // This test verifies that absl::make_index_sequence can handle large arguments // without blowing up template instantiation stack, going OOM or taking forever // to compile (there is hard 15 minutes limit imposed by forge). TEST(IntegerSequenceTest, MakeIndexSequencePerformance) { // O(log N) template instantiations. // We only need an alias here, but instantiate a variable to silence warnings // for unused typedefs in some compilers. ABSL_ATTRIBUTE_UNUSED absl::make_index_sequence<(1 << 16) - 1> seq; // O(N) template instantiations. CountAll(absl::make_index_sequence<(1 << 8) - 1>()); } template auto ApplyFromTupleImpl(F f, const Tup& tup, absl::index_sequence) -> decltype(f(std::get(tup)...)) { return f(std::get(tup)...); } template using TupIdxSeq = absl::make_index_sequence::value>; template auto ApplyFromTuple(F f, const Tup& tup) -> decltype(ApplyFromTupleImpl(f, tup, TupIdxSeq{})) { return ApplyFromTupleImpl(f, tup, TupIdxSeq{}); } template std::string Fmt(const T& x) { std::ostringstream os; os << x; return os.str(); } struct PoorStrCat { template std::string operator()(const Args&... args) const { std::string r; for (const auto& e : {Fmt(args)...}) r += e; return r; } }; template std::vector TupStringVecImpl(const Tup& tup, absl::index_sequence) { return {Fmt(std::get(tup))...}; } template std::vector TupStringVec(const std::tuple& tup) { return TupStringVecImpl(tup, absl::index_sequence_for()); } TEST(MakeIndexSequenceTest, ApplyFromTupleExample) { PoorStrCat f{}; EXPECT_EQ("12abc3.14", f(12, "abc", 3.14)); EXPECT_EQ("12abc3.14", ApplyFromTuple(f, std::make_tuple(12, "abc", 3.14))); } TEST(IndexSequenceForTest, Basic) { StaticAssertTypeEq, absl::index_sequence_for<>>(); StaticAssertTypeEq, absl::index_sequence_for>(); StaticAssertTypeEq, absl::index_sequence_for>(); } TEST(IndexSequenceForTest, Example) { EXPECT_THAT(TupStringVec(std::make_tuple(12, "abc", 3.14)), ElementsAre("12", "abc", "3.14")); } } // namespace