/* * Copyright 2011-present Facebook, Inc. * * 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 #include using namespace folly; TEST(DiscriminatedPtr, Basic) { struct Foo {}; struct Bar {}; typedef DiscriminatedPtr Ptr; int a = 10; Ptr p; EXPECT_TRUE(p.empty()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); p.set(&a); EXPECT_FALSE(p.empty()); EXPECT_FALSE(p.hasType()); EXPECT_TRUE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_EQ(&a, p.get_nothrow()); EXPECT_EQ(&a, static_cast(p).get_nothrow()); EXPECT_EQ(&a, p.get()); EXPECT_EQ(&a, static_cast(p).get()); EXPECT_EQ(static_cast(nullptr), p.get_nothrow()); EXPECT_THROW({ p.get(); }, std::invalid_argument); Foo foo; p.set(&foo); EXPECT_FALSE(p.empty()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_TRUE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_EQ(static_cast(nullptr), p.get_nothrow()); p.clear(); EXPECT_TRUE(p.empty()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); EXPECT_FALSE(p.hasType()); } TEST(DiscriminatedPtr, Apply) { struct Foo {}; struct Visitor { std::string operator()(int* /* ptr */) { return "int"; } std::string operator()(const int* /* ptr */) { return "const int"; } std::string operator()(Foo* /* ptr */) { return "Foo"; } std::string operator()(const Foo* /* ptr */) { return "const Foo"; } }; typedef DiscriminatedPtr Ptr; Ptr p; int a = 0; p.set(&a); EXPECT_EQ("int", p.apply(Visitor())); EXPECT_EQ("const int", static_cast(p).apply(Visitor())); Foo foo; p.set(&foo); EXPECT_EQ("Foo", p.apply(Visitor())); EXPECT_EQ("const Foo", static_cast(p).apply(Visitor())); EXPECT_EQ("Foo", apply_visitor(Visitor(), p)); EXPECT_EQ("const Foo", apply_visitor(Visitor(), static_cast(p))); EXPECT_EQ("Foo", apply_visitor(Visitor(), std::move(p))); p.clear(); EXPECT_THROW({ p.apply(Visitor()); }, std::invalid_argument); } TEST(DiscriminatedPtr, ApplyVoid) { struct Foo {}; struct Visitor { void operator()(int* /* ptr */) { result = "int"; } void operator()(const int* /* ptr */) { result = "const int"; } void operator()(Foo* /* ptr */) { result = "Foo"; } void operator()(const Foo* /* ptr */) { result = "const Foo"; } std::string result; }; typedef DiscriminatedPtr Ptr; Ptr p; Visitor v; int a = 0; p.set(&a); p.apply(v); EXPECT_EQ("int", v.result); static_cast(p).apply(v); EXPECT_EQ("const int", v.result); Foo foo; p.set(&foo); p.apply(v); EXPECT_EQ("Foo", v.result); static_cast(p).apply(v); EXPECT_EQ("const Foo", v.result); p.clear(); EXPECT_THROW({ p.apply(v); }, std::invalid_argument); }