#include <boost/mpl/has_xxx.hpp>
#include <folly/Likely.h>
+#include <folly/Optional.h>
#include <folly/Traits.h>
#include <folly/dynamic.h>
template<typename T>
struct Dereferencer {
static inline void derefToCache(
- T* /* mem */, const dynamic::const_item_iterator& /* it */) {
+ Optional<T>* /* mem */,
+ const dynamic::const_item_iterator& /* it */) {
throw TypeError("array", dynamic::Type::OBJECT);
}
- static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
- new (mem) T(convertTo<T>(*it));
+ static inline void derefToCache(
+ Optional<T>* mem,
+ const dynamic::const_iterator& it) {
+ mem->emplace(convertTo<T>(*it));
}
};
template<typename F, typename S>
struct Dereferencer<std::pair<F, S>> {
- static inline void
- derefToCache(std::pair<F, S>* mem, const dynamic::const_item_iterator& it) {
- new (mem) std::pair<F, S>(
- convertTo<F>(it->first), convertTo<S>(it->second)
- );
+ static inline void derefToCache(
+ Optional<std::pair<F, S>>* mem,
+ const dynamic::const_item_iterator& it) {
+ mem->emplace(convertTo<F>(it->first), convertTo<S>(it->second));
}
// Intentional duplication of the code in Dereferencer
template <typename T>
- static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
- new (mem) T(convertTo<T>(*it));
+ static inline void derefToCache(
+ Optional<T>* mem,
+ const dynamic::const_iterator& it) {
+ mem->emplace(convertTo<T>(*it));
}
};
typedef typename T::value_type ttype;
- mutable ttype cache_;
- mutable bool valid_;
+ mutable Optional<ttype> cache_;
void increment() {
++this->base_reference();
- valid_ = false;
+ cache_ = none;
}
ttype& dereference() const {
- if (LIKELY(!valid_)) {
- cache_.~ttype();
+ if (!cache_) {
Dereferencer<ttype>::derefToCache(&cache_, this->base_reference());
- valid_ = true;
}
- return cache_;
+ return cache_.value();
}
public:
- explicit Transformer(const It& it)
- : Transformer::iterator_adaptor_(it), valid_(false) {}
+ explicit Transformer(const It& it) : Transformer::iterator_adaptor_(it) {}
};
// conversion factory
dynamic::array(1, dynamic::array(), 3))),
TypeError);
}
+
+static int constructB = 0;
+static int destroyB = 0;
+static int ticker = 0;
+struct B {
+ struct BException : std::exception {};
+
+ /* implicit */ B(int x) : x_(x) {
+ if (ticker-- == 0) {
+ throw BException();
+ }
+ constructB++;
+ }
+ B(const B& o) : x_(o.x_) {
+ constructB++;
+ }
+ ~B() {
+ destroyB++;
+ }
+ int x_;
+};
+namespace folly {
+template <>
+struct DynamicConverter<B> {
+ static B convert(const dynamic& d) {
+ return B(convertTo<int>(d));
+ }
+};
+}
+
+TEST(DynamicConverter, double_destroy) {
+ dynamic d = dynamic::array(1, 3, 5, 7, 9, 11, 13, 15, 17);
+ ticker = 3;
+
+ EXPECT_THROW(convertTo<std::vector<B>>(d), B::BException);
+ EXPECT_EQ(constructB, destroyB);
+}