public:
// C++11 21.4.2 construct/copy/destroy
- explicit basic_fbstring(const A& /*a*/ = A()) noexcept {
+
+ // Note: while the following two constructors can be (and previously were)
+ // collapsed into one constructor written this way:
+ //
+ // explicit basic_fbstring(const A& a = A()) noexcept { }
+ //
+ // This can cause Clang (at least version 3.7) to fail with the error:
+ // "chosen constructor is explicit in copy-initialization ...
+ // in implicit initialization of field '(x)' with omitted initializer"
+ //
+ // if used in a struct which is default-initialized. Hence the split into
+ // these two separate constructors.
+
+ basic_fbstring() noexcept : basic_fbstring(A()) {
+ }
+
+ explicit basic_fbstring(const A&) noexcept {
}
basic_fbstring(const basic_fbstring& str)
#include <folly/FBString.h>
+#include <atomic>
#include <cstdlib>
#include <list>
EXPECT_EQ('\0', *s.c_str());
}
+namespace {
+/*
+ * t8968589: Clang 3.7 refused to compile w/ certain constructors (specifically
+ * those that were "explicit" and had a defaulted parameter, if they were used
+ * in structs which were default-initialized). Exercise these just to ensure
+ * they compile.
+ *
+ * In diff D2632953 the old constructor:
+ * explicit basic_fbstring(const A& a = A()) noexcept;
+ *
+ * was split into these two, as a workaround:
+ * basic_fbstring() noexcept;
+ * explicit basic_fbstring(const A& a) noexcept;
+ */
+
+struct TestStructDefaultAllocator {
+ folly::basic_fbstring<char> stringMember;
+};
+
+template <class A>
+struct TestStructWithAllocator {
+ folly::basic_fbstring<char, std::char_traits<char>, A> stringMember;
+};
+
+std::atomic<size_t> allocatorConstructedCount(0);
+struct TestStructStringAllocator : std::allocator<char> {
+ TestStructStringAllocator() {
+ ++ allocatorConstructedCount;
+ }
+};
+
+} // anon namespace
+
+TEST(FBStringCtorTest, DefaultInitStructDefaultAlloc) {
+ TestStructDefaultAllocator t1 { };
+ EXPECT_TRUE(t1.stringMember.empty());
+}
+
+TEST(FBStringCtorTest, DefaultInitStructAlloc) {
+ EXPECT_EQ(allocatorConstructedCount.load(), 0);
+ TestStructWithAllocator<TestStructStringAllocator> t2;
+ EXPECT_TRUE(t2.stringMember.empty());
+ EXPECT_EQ(allocatorConstructedCount.load(), 1);
+}
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);