180 likes | 325 Vues
Optional?. Agenda. Type traits intro Interface & usage Caveats. Why?. Uninitialized variables cause lots of bugs Removes much need for 2-stage initialization of objects A cheap 0 or 1 element container Internal storage. Much preferable over scoped_ptr + heap allocation
E N D
Agenda • Type traits intro • Interface & usage • Caveats
Why? • Uninitialized variables cause lots of bugs • Removes much need for 2-stage initialization of objects • A cheap 0 or 1 element container • Internal storage. Much preferable over scoped_ptr + heap allocation • Much less bloat & faster compilation than boost::optional
Type traits are meta functions! is_integer<int>::value => true is_floating_point<int>::value => false alignment_of<Vec3>::value => 128 remove_reference<T&>::type => T is_same<int, float>::value => false is_convertible<int, uint>::value => true • Very useful when writing generic code
Implemented with template specialization // Default template<class T> structis_floating_point { enum { value = false; } }; template<> structis_floating_point<float> { enum { value = true; } }; template<> structis_floating_point<double> { enum { value = true; } };
Useful for static dispatch, among other things.. template<class T> T my_cool_algorithm(T t) { return my_cool_algorithm_impl<T, is_floating_point<T>::value>(t); } template<class T, bool> T my_cool_algorithm_impl(T t); template<class T, true> T my_cool_algorithm_impl(T t) { // int optimized version } template<class T, false> T my_cool_algorithm_impl(T t) { // float optimized version }
Optional interface struct Nothing {}; template <class T> class Optional { Optional(); Optional(Nothing); // Note implicit Optional(const T& value); // Note implicit Optional(const Optional<T>& copy); Optional<T>& operator=(Nothing); Optional<T>& operator=(const T& value); Optional<T>& operator=(const Optional<T>& rhs); bool isSet() const; /// @pre isSet() T& get(); const T& get() const; }; // Override placement new to allow constructing elements without copying template<class T> inline void* operator new(size_t, fb::Optional<T>& optional); // Convenience function template<class T> const T& getValueOr(const Optional<T>& optional, const T& defaultValue) const; template<class T> T& getValueOr(Optional<T>& optional, T& defaultValue) const;
Basic usage Optional<int> i; ASSERT(!i.isSet()); i = 23; ASSERT(i.isSet() && i.get()==23); i = Nothing(); ASSERT(!i.isSet());
Return from functions // C style bool sqrt(double n, double& result); Optional<double> sqrt(double n); • Client code won’t forget to check the bool • All-or-nothing guarantee, can’t break output variables
Member variables not always valid class X { Optional<uint> m_resultCache; }; • Clearer than using -1 or other "invalid values“
Single item container class X { Optional<Weapon> m_activeWeapon; }; • Does not require DefaultConstructible objects • No heap allocations! Uses placement new internally • Useful to store RAII objects
Expressive interface class X { void setLookForEnemyAroundPosition( const Optional<Vec3>& position); const Optional<Vec3>& getLookForEnemyAroundPosition(); };
Simplifying code class Target { // Remove, use optional instead! bool isValid() const; }; void foo(Optional<Target> t); void bar(Target t); void baz(Target t); • Often little code that need complexity of invalid objects • Helps maintenance – expressive client code
Caveats in current implementation • Aligned types double in size • No implicit bool conversion • Unnecessary branch for some types Most of them can be fixed simply
Aligned types double in size sizeof(Optional<Vec3>) == 2 * sizeof(Vec3) For Vec3, the pad data can be used
No implicit bool conversion • Missing safe implicit type conversion to bool if (Optional<double> xRoot = sqrt(x))
Unnecessary branch for some types ~Optional() { if (!HasTrivialDestructor<T>::Value && m_initialized) m_storage.destruct(); } Will get C++0x features in all of our compilers soon Until then types can be registered as having a trivial, no-op destructor
Further reading Unit tests in OptionalTest.cpp Static tests in HasTrivialDestructor.cpp, AlignedStorage.cpp and Optional.cpp Design rationale for boost.optional http://www.boost.org/doc/libs/1_38_0/libs/optional/doc/html/boost_optional/development.html Nullablei C# http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx