/* dwarfpp: C++ binding for a useful subset of libdwarf, plus extra goodies. * * opt.hpp: utility code for optional data * * Copyright (c) 2008--17, Stephen Kell. For licensing information, see the * LICENSE file in the root of the libdwarfpp tree. */ #ifndef DWARFPP_OPT_HPP_ #define DWARFPP_OPT_HPP_ #include #include namespace dwarf { namespace core { struct iterator_base; struct type_die; template struct iterator_df; } namespace spec { /* FIXME: this stuff arguably doesn't belong in spec, but in a util area. */ /* (So do the exception types we define, like Not_supported and No_entry, * arguably. FIXME: move those.) */ using std::shared_ptr; using boost::optional; /* We use this to encode optional attributes. It's like boost::optional, * but since pointers already model the optional concept, we avoid a double- * indirection (**attr) to get the value of a pointer-valued attribute. */ // FIXME: don't hardcode std::shared_ptr here template struct opt : optional { typedef optional super; // needs g++ 4.8+! or some other C++11-compliant compiler using optional::optional; operator bool() const { return this->is_initialized(); } }; /* END the non-specialised opt<> case. */ /* BEGIN the opt<> case specialized for shared_ptr. */ template struct opt > : shared_ptr { typedef shared_ptr super; /* forward the underlying constructors */ using shared_ptr::shared_ptr; operator bool() const { return !!static_cast(*this); } }; /* Similarly, we need one for iterators, i.e. things which extend * iterator_base. Can we express this specialization? It seems that * std::enable_if can do this. This is why we need the extra Enabler * template argument, though. (We could try the more direct approach, * but the compiler complains that the specialization doesn't name the * template argument T. I'm not convinced that this complaint is valid.) */ template struct opt< T, typename std::enable_if::value >::type > : T { typedef T super; /* forward the underlying constructors */ using T::T; // operator bool is already taken care of in iterator_base }; /* These do the opposite: unspecialise, to reinstate the double indirection. * We only need them in encap.hpp where we have macros * that want to do attribute_value(*a) for any argument a. Normally the caller * would know not to do *a, but in that macroised generic code, we can't know. * So we have the code do *deref_opt(), which no-ops the unwanted deref. */ template std::shared_ptr deref_opt(const opt >& arg) { return arg; } template T deref_opt(const opt& arg) { return *arg; } template T deref_opt(const opt< T, typename std::enable_if::value, T >::type >& arg) { return arg; } } /* end namespace spec */ } #endif