cppbind: Refactor to use C++11+ type_traits

This commit is contained in:
Thomas Geymayer 2018-01-21 13:02:43 +01:00
parent 9078a085c3
commit af5833cbc5
12 changed files with 332 additions and 275 deletions

View File

@ -492,13 +492,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS_C} ${MSVC_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
check_cxx_source_compiles(" include(CheckCXXFeatures)
#include <utility>
#include <type_traits>
std::make_index_sequence<0> t;
int main() { return 0; }"
HAVE_STD_INDEX_SEQUENCE
)
# use BEFORE to ensure local directories are used first, # use BEFORE to ensure local directories are used first,
# ahead of system-installed libs # ahead of system-installed libs

View File

@ -0,0 +1,30 @@
check_cxx_source_compiles("
#include <utility>
#include <type_traits>
std::make_index_sequence<0> t;
int main() {}" HAVE_STD_INDEX_SEQUENCE
)
check_cxx_source_compiles("
#include <type_traits>
std::remove_cv_t<const int> t;
int main() {}" HAVE_STD_REMOVE_CV_T
)
check_cxx_source_compiles("
#include <type_traits>
std::remove_cvref_t<const int&> t;
int main() {}" HAVE_STD_REMOVE_CVREF_T
)
check_cxx_source_compiles("
#include <type_traits>
std::enable_if_t<true, int> t;
int main() {}" HAVE_STD_ENABLE_IF_T
)
check_cxx_source_compiles("
#include <type_traits>
std::bool_constant<true> t;
int main() {}" HAVE_STD_BOOL_CONSTANT
)

View File

@ -15,6 +15,7 @@ foreach( mylibfolder
nasal/cppbind nasal/cppbind
props props
serial serial
std
structure structure
threads threads
timing timing

View File

@ -9,7 +9,6 @@ set(HEADERS
SVGpreserveAspectRatio.hxx SVGpreserveAspectRatio.hxx
argparse.hxx argparse.hxx
interpolator.hxx interpolator.hxx
integer_sequence.hxx
make_new.hxx make_new.hxx
sg_dir.hxx sg_dir.hxx
sg_hash.hxx sg_hash.hxx
@ -57,10 +56,6 @@ add_executable(test_CSSBorder CSSBorder_test.cxx)
add_test(CSSBorder ${EXECUTABLE_OUTPUT_PATH}/test_CSSBorder) add_test(CSSBorder ${EXECUTABLE_OUTPUT_PATH}/test_CSSBorder)
target_link_libraries(test_CSSBorder ${TEST_LIBS}) target_link_libraries(test_CSSBorder ${TEST_LIBS})
add_executable(test_integer_sequence integer_sequence_test.cxx)
add_test(integer_sequence ${EXECUTABLE_OUTPUT_PATH}/test_integer_sequence)
target_link_libraries(test_integer_sequence ${TEST_LIBS})
add_executable(test_tabbed_values tabbed_values_test.cxx) add_executable(test_tabbed_values tabbed_values_test.cxx)
add_test(tabbed_values ${EXECUTABLE_OUTPUT_PATH}/test_tabbed_values) add_test(tabbed_values ${EXECUTABLE_OUTPUT_PATH}/test_tabbed_values)
target_link_libraries(test_tabbed_values ${TEST_LIBS}) target_link_libraries(test_tabbed_values ${TEST_LIBS})

View File

@ -24,17 +24,16 @@
#include "NasalObjectHolder.hxx" #include "NasalObjectHolder.hxx"
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/misc/integer_sequence.hxx> #include <simgear/std/integer_sequence.hxx>
#include <simgear/std/type_traits.hxx>
#include <simgear/structure/SGWeakReferenced.hxx> #include <simgear/structure/SGWeakReferenced.hxx>
#include <simgear/structure/SGWeakPtr.hxx> #include <simgear/structure/SGWeakPtr.hxx>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/call_traits.hpp> #include <boost/call_traits.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/mpl/has_xxx.hpp> #include <boost/mpl/has_xxx.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/utility/enable_if.hpp>
#include <map> #include <map>
@ -62,10 +61,7 @@ namespace osg
} }
template<class T> template<class T>
inline typename boost::enable_if< inline std::enable_if_t<std::is_pointer<T>::value, T>
boost::is_pointer<T>,
T
>::type
get_pointer(T ptr) get_pointer(T ptr)
{ {
return ptr; return ptr;
@ -101,8 +97,8 @@ namespace nasal
class GhostMetadata class GhostMetadata
{ {
public: public:
typedef void(*Deleter)(void*); using Deleter = void(*)(void*);
typedef std::vector<std::pair<Deleter, void*> > DestroyList; using DestroyList = std::vector<std::pair<Deleter, void*>>;
static DestroyList _destroy_list; static DestroyList _destroy_list;
@ -154,19 +150,6 @@ namespace nasal
}; };
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type) BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
template<class T>
struct reduced_type
{
typedef typename boost::remove_cv<
typename boost::remove_reference<T>::type
>::type type;
};
template<class T1, class T2>
struct reduced_is_same:
public boost::is_same<typename reduced_type<T1>::type, T2>
{};
} }
/** @brief Destroy all ghost queued for deletion. /** @brief Destroy all ghost queued for deletion.
@ -178,8 +161,8 @@ namespace nasal
*/ */
void ghostProcessDestroyList(); void ghostProcessDestroyList();
typedef SGSharedPtr<internal::MethodHolder> MethodHolderPtr; using MethodHolderPtr = SGSharedPtr<internal::MethodHolder>;
typedef SGWeakPtr<internal::MethodHolder> MethodHolderWeakPtr; using MethodHolderWeakPtr = SGWeakPtr<internal::MethodHolder>;
// Dummy template to create shorter and easy to understand compile errors if // Dummy template to create shorter and easy to understand compile errors if
// trying to wrap the wrong type as a Ghost. // trying to wrap the wrong type as a Ghost.
@ -187,9 +170,10 @@ namespace nasal
class Ghost class Ghost
{ {
public: public:
BOOST_STATIC_ASSERT(("Ghost can only wrap shared pointer!" static_assert(
&& is_strong_ref<T>::value is_strong_ref<T>::value,
)); "Ghost can only wrap shared pointer!"
);
static Ghost& init(const std::string& name); static Ghost& init(const std::string& name);
static bool isInit(); static bool isInit();
@ -209,7 +193,7 @@ namespace nasal
* int myMember(); * int myMember();
* void doSomethingElse(const nasal::CallContext& ctx); * void doSomethingElse(const nasal::CallContext& ctx);
* } * }
* typedef boost::shared_ptr<MyClass> MyClassPtr; * using MyClassPtr = boost::shared_ptr<MyClass>;
* *
* std::string myOtherFreeMember(int num); * std::string myOtherFreeMember(int num);
* *
@ -235,29 +219,22 @@ namespace nasal
* @endcode * @endcode
*/ */
template<class T> template<class T>
class Ghost<T, typename boost::enable_if<is_strong_ref<T> >::type>: class Ghost<T, std::enable_if_t<is_strong_ref<T>::value>>:
public internal::GhostMetadata public internal::GhostMetadata
{ {
// Shared pointer required for Ghost (no weak pointer!)
BOOST_STATIC_ASSERT((is_strong_ref<T>::value));
public: public:
typedef typename T::element_type raw_type; using raw_type = typename T::element_type;
typedef typename shared_ptr_traits<T>::strong_ref strong_ref; using strong_ref = typename shared_ptr_traits<T>::strong_ref;
typedef typename shared_ptr_traits<T>::weak_ref weak_ref; using weak_ref = typename shared_ptr_traits<T>::weak_ref;
typedef naRef (raw_type::*member_func_t)(const CallContext&); using member_func_t = naRef (raw_type::*)(const CallContext&);
typedef naRef (*free_func_t)(raw_type&, const CallContext&); using free_func_t = naRef (*)(raw_type&, const CallContext&);
typedef boost::function<naRef(raw_type&, naContext)> getter_t; using getter_t = boost::function<naRef(raw_type&, naContext)>;
typedef boost::function<void( raw_type&, naContext, naRef)> setter_t; using setter_t = boost::function<void( raw_type&, naContext, naRef)>;
typedef boost::function<naRef(raw_type&, const CallContext&)> method_t; using method_t = boost::function<naRef(raw_type&, const CallContext&)>;
typedef boost::function<bool( raw_type&, using fallback_getter_t =
naContext, boost::function<bool(raw_type&, naContext, const std::string&, naRef&)>;
const std::string&, using fallback_setter_t =
naRef& )> fallback_getter_t; boost::function<bool(raw_type&, naContext, const std::string&, naRef)>;
typedef boost::function<bool( raw_type&,
naContext,
const std::string&,
naRef )> fallback_setter_t;
template<class Ret, class... Args> template<class Ret, class... Args>
using method_variadic_t = boost::function<Ret (raw_type&, Args...)>; using method_variadic_t = boost::function<Ret (raw_type&, Args...)>;
@ -272,8 +249,8 @@ namespace nasal
protected: protected:
typedef SGSharedPtr<MethodHolder> SharedPtr; using SharedPtr = SGSharedPtr<MethodHolder>;
typedef SGWeakPtr<MethodHolder> WeakPtr; using WeakPtr = SGWeakPtr<MethodHolder>;
method_t _method; method_t _method;
@ -372,7 +349,7 @@ namespace nasal
MethodHolderPtr func; MethodHolderPtr func;
}; };
typedef std::map<std::string, member_t> MemberMap; using MemberMap = std::map<std::string, member_t>;
/** /**
* Register a new ghost type. * Register a new ghost type.
@ -409,19 +386,18 @@ namespace nasal
* @endcode * @endcode
*/ */
template<class BaseGhost> template<class BaseGhost>
typename boost::enable_if std::enable_if_t<
< std::is_base_of<GhostMetadata, BaseGhost>::value,
boost::is_base_of<GhostMetadata, BaseGhost>, Ghost&
Ghost >
>::type&
bases() bases()
{ {
BOOST_STATIC_ASSERT static_assert(
(( std::is_base_of<typename BaseGhost::raw_type, raw_type>::value,
boost::is_base_of<typename BaseGhost::raw_type, raw_type>::value "Not a base class!"
)); );
typedef typename BaseGhost::strong_ref base_ref; using base_ref = typename BaseGhost::strong_ref;
BaseGhost* base = BaseGhost::getSingletonPtr(); BaseGhost* base = BaseGhost::getSingletonPtr();
base->addDerived( base->addDerived(
@ -467,17 +443,16 @@ namespace nasal
* @endcode * @endcode
*/ */
template<class Base> template<class Base>
typename boost::disable_if std::enable_if_t<
< !std::is_base_of<GhostMetadata, Base>::value,
boost::is_base_of<GhostMetadata, Base>, Ghost&
Ghost >
>::type&
bases() bases()
{ {
BOOST_STATIC_ASSERT static_assert(
(( std::is_base_of<typename Ghost<Base>::raw_type, raw_type>::value,
boost::is_base_of<typename Ghost<Base>::raw_type, raw_type>::value "Not a base class!"
)); );
return bases< Ghost<Base> >(); return bases< Ghost<Base> >();
} }
@ -853,10 +828,10 @@ namespace nasal
) )
{ {
static_assert( static_assert(
boost::is_convertible<raw_type&, Type>::value, std::is_convertible<raw_type&, Type>::value,
//|| boost::is_convertible<raw_type*, Type>::value //|| std::is_convertible<raw_type*, Type>::value
// TODO check how to do it with pointer... // TODO check how to do it with pointer...
"First parameter can not be converted from the Ghost raw_type" "First parameter can not be converted from the Ghost raw_type!"
); );
return method(name, method_variadic_t<Ret, Args...>(fn)); return method(name, method_variadic_t<Ret, Args...>(fn));
@ -868,11 +843,11 @@ namespace nasal
*/ */
template<class RefType> template<class RefType>
static static
typename boost::enable_if_c< std::enable_if_t<
boost::is_same<RefType, strong_ref>::value std::is_same<RefType, strong_ref>::value
|| boost::is_same<RefType, weak_ref>::value, || std::is_same<RefType, weak_ref>::value,
naRef naRef
>::type >
makeGhost(naContext c, RefType const& ref_ptr) makeGhost(naContext c, RefType const& ref_ptr)
{ {
strong_ref ref(ref_ptr); strong_ref ref(ref_ptr);
@ -927,13 +902,10 @@ namespace nasal
if( !naIsVector(na_parents) ) if( !naIsVector(na_parents) )
return strong_ref(); return strong_ref();
typedef std::vector<naRef> naRefs; auto parents = from_nasal<std::vector<naRef>>(c, na_parents);
naRefs parents = from_nasal<naRefs>(c, na_parents); for(auto parent: parents)
for( naRefs::const_iterator parent = parents.begin();
parent != parents.end();
++parent )
{ {
strong_ref ref = fromNasal(c, *parent); strong_ref ref = fromNasal(c, parent);
if( get_pointer(ref) ) if( get_pointer(ref) )
return ref; return ref;
} }
@ -985,8 +957,9 @@ namespace nasal
static naGhostType _ghost_type_strong, //!< Stored as shared pointer static naGhostType _ghost_type_strong, //!< Stored as shared pointer
_ghost_type_weak; //!< Stored as weak shared pointer _ghost_type_weak; //!< Stored as weak shared pointer
typedef naRef (*to_nasal_t)(naContext, const strong_ref&, bool); using to_nasal_t = naRef (*)(naContext, const strong_ref&, bool);
typedef strong_ref (*from_nasal_t)(naContext, naRef); using from_nasal_t = strong_ref (*)(naContext, naRef);
struct DerivedInfo struct DerivedInfo
{ {
to_nasal_t to_nasal; to_nasal_t to_nasal;
@ -999,7 +972,7 @@ namespace nasal
{} {}
}; };
typedef std::vector<DerivedInfo> DerivedList; using DerivedList = std::vector<DerivedInfo>;
DerivedList _derived_types; DerivedList _derived_types;
static bool isInstance(naGhostType* ghost_type, bool& is_weak) static bool isInstance(naGhostType* ghost_type, bool& is_weak)
@ -1013,13 +986,10 @@ namespace nasal
template<class RefPtr, bool is_weak> template<class RefPtr, bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<!is_weak, RefPtr>
!is_weak,
RefPtr
>::type
getPtr(void* ptr) getPtr(void* ptr)
{ {
typedef shared_ptr_storage<strong_ref> storage_type; using storage_type = shared_ptr_storage<strong_ref>;
if( ptr ) if( ptr )
return storage_type::template get<RefPtr>( return storage_type::template get<RefPtr>(
static_cast<typename storage_type::storage_type*>(ptr) static_cast<typename storage_type::storage_type*>(ptr)
@ -1030,13 +1000,13 @@ namespace nasal
template<class RefPtr, bool is_weak> template<class RefPtr, bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<
is_weak && supports_weak_ref<T>::value, is_weak && supports_weak_ref<T>::value,
RefPtr RefPtr
>::type >
getPtr(void* ptr) getPtr(void* ptr)
{ {
typedef shared_ptr_storage<weak_ref> storage_type; using storage_type = shared_ptr_storage<weak_ref>;
if( ptr ) if( ptr )
return storage_type::template get<RefPtr>( return storage_type::template get<RefPtr>(
static_cast<typename storage_type::storage_type*>(ptr) static_cast<typename storage_type::storage_type*>(ptr)
@ -1047,10 +1017,10 @@ namespace nasal
template<class RefPtr, bool is_weak> template<class RefPtr, bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<
is_weak && !supports_weak_ref<T>::value, is_weak && !supports_weak_ref<T>::value,
RefPtr RefPtr
>::type >
getPtr(void* ptr) getPtr(void* ptr)
{ {
return RefPtr(); return RefPtr();
@ -1066,10 +1036,10 @@ namespace nasal
template<class BaseGhost> template<class BaseGhost>
static static
typename boost::enable_if std::enable_if_t<
< boost::is_polymorphic<typename BaseGhost::raw_type>, std::is_polymorphic<typename BaseGhost::raw_type>::value,
naRef naRef
>::type >
toNasal( naContext c, toNasal( naContext c,
const typename BaseGhost::strong_ref& base_ref, const typename BaseGhost::strong_ref& base_ref,
bool strong ) bool strong )
@ -1078,10 +1048,10 @@ namespace nasal
// Check first if passed pointer can by converted to instance of class // Check first if passed pointer can by converted to instance of class
// this ghost wraps. // this ghost wraps.
if( !boost::is_same if( !std::is_same<
< typename BaseGhost::raw_type, typename BaseGhost::raw_type,
typename Ghost::raw_type typename Ghost::raw_type
>::value >::value
&& dynamic_cast<const typename Ghost::raw_type*>(ptr) != ptr ) && dynamic_cast<const typename Ghost::raw_type*>(ptr) != ptr )
return naNil(); return naNil();
@ -1120,13 +1090,13 @@ namespace nasal
template<class BaseGhost> template<class BaseGhost>
static static
typename boost::disable_if std::enable_if_t<
< boost::is_polymorphic<typename BaseGhost::raw_type>, !std::is_polymorphic<typename BaseGhost::raw_type>::value,
naRef naRef
>::type >
toNasal( naContext c, toNasal( naContext c,
const typename BaseGhost::strong_ref& ref, const typename BaseGhost::strong_ref& ref,
bool strong ) bool strong )
{ {
// For non polymorphic classes there is no possibility to get the actual // For non polymorphic classes there is no possibility to get the actual
// dynamic type, therefore we can only use its static type. // dynamic type, therefore we can only use its static type.
@ -1149,7 +1119,7 @@ namespace nasal
template<class Ret> template<class Ret>
getter_t to_getter(Ret (raw_type::*getter)() const) getter_t to_getter(Ret (raw_type::*getter)() const)
{ {
typedef typename boost::call_traits<Ret>::param_type param_type; using param_type = typename boost::call_traits<Ret>::param_type;
naRef(*to_nasal_)(naContext, param_type) = &to_nasal; naRef(*to_nasal_)(naContext, param_type) = &to_nasal;
// Getter signature: naRef(raw_type&, naContext) // Getter signature: naRef(raw_type&, naContext)
@ -1202,7 +1172,7 @@ namespace nasal
*/ */
template<class Ret> template<class Ret>
static static
typename boost::disable_if<boost::is_void<Ret>, naRef>::type std::enable_if_t<!std::is_void<Ret>::value, naRef>
method_invoker method_invoker
( (
const boost::function<Ret (raw_type&, const CallContext&)>& func, const boost::function<Ret (raw_type&, const CallContext&)>& func,
@ -1218,7 +1188,7 @@ namespace nasal
*/ */
template<class Ret> template<class Ret>
static static
typename boost::enable_if<boost::is_void<Ret>, naRef>::type std::enable_if_t<std::is_void<Ret>::value, naRef>
method_invoker method_invoker
( (
const boost::function<Ret (raw_type&, const CallContext&)>& func, const boost::function<Ret (raw_type&, const CallContext&)>& func,
@ -1236,10 +1206,10 @@ namespace nasal
*/ */
template<class Arg> template<class Arg>
static static
typename boost::disable_if< std::enable_if_t<
internal::reduced_is_same<Arg, CallContext>, !std::is_same<std::remove_cvref_t<Arg>, CallContext>::value,
typename from_nasal_ptr<Arg>::return_type typename from_nasal_ptr<Arg>::return_type
>::type >
arg_from_nasal(const CallContext& ctx, size_t index) arg_from_nasal(const CallContext& ctx, size_t index)
{ {
return ctx.requireArg<Arg>(index); return ctx.requireArg<Arg>(index);
@ -1250,19 +1220,21 @@ namespace nasal
*/ */
template<class Arg> template<class Arg>
static static
typename boost::enable_if< std::enable_if_t<
internal::reduced_is_same<Arg, CallContext>, std::is_same<std::remove_cvref_t<Arg>, CallContext>::value,
typename from_nasal_ptr<Arg>::return_type typename from_nasal_ptr<Arg>::return_type
>::type >
arg_from_nasal(const CallContext& ctx, size_t) arg_from_nasal(const CallContext& ctx, size_t)
{ {
// Either const CallContext& or CallContext, non-const reference // Either const CallContext& or CallContext, non-const reference
// does not make sense. // does not make sense.
BOOST_STATIC_ASSERT( (!boost::is_same<Arg, CallContext&>::value) ); static_assert(
!boost::is_same<Arg, CallContext&>::value,
"Only const reference and value make sense!");
return ctx; return ctx;
}; };
typedef std::unique_ptr<Ghost> GhostPtr; using GhostPtr = std::unique_ptr<Ghost>;
MemberMap _members; MemberMap _members;
fallback_getter_t _fallback_getter; fallback_getter_t _fallback_getter;
fallback_setter_t _fallback_setter; fallback_setter_t _fallback_setter;
@ -1302,13 +1274,10 @@ namespace nasal
template<bool is_weak> template<bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<!is_weak, naRef>
!is_weak,
naRef
>::type
create(naContext c, const strong_ref& ref_ptr) create(naContext c, const strong_ref& ref_ptr)
{ {
typedef shared_ptr_storage<strong_ref> storage_type; using storage_type = shared_ptr_storage<strong_ref>;
return naNewGhost2( c, return naNewGhost2( c,
&Ghost::_ghost_type_strong, &Ghost::_ghost_type_strong,
storage_type::ref(ref_ptr) ); storage_type::ref(ref_ptr) );
@ -1316,13 +1285,13 @@ namespace nasal
template<bool is_weak> template<bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<
is_weak && supports_weak_ref<T>::value, is_weak && supports_weak_ref<T>::value,
naRef naRef
>::type >
create(naContext c, const strong_ref& ref_ptr) create(naContext c, const strong_ref& ref_ptr)
{ {
typedef shared_ptr_storage<weak_ref> storage_type; using storage_type = shared_ptr_storage<weak_ref>;
return naNewGhost2( c, return naNewGhost2( c,
&Ghost::_ghost_type_weak, &Ghost::_ghost_type_weak,
storage_type::ref(ref_ptr) ); storage_type::ref(ref_ptr) );
@ -1330,10 +1299,10 @@ namespace nasal
template<bool is_weak> template<bool is_weak>
static static
typename boost::enable_if_c< std::enable_if_t<
is_weak && !supports_weak_ref<T>::value, is_weak && !supports_weak_ref<T>::value,
naRef naRef
>::type >
create(naContext, const strong_ref&) create(naContext, const strong_ref&)
{ {
return naNil(); return naNil();
@ -1342,7 +1311,7 @@ namespace nasal
template<class Type> template<class Type>
static void destroy(void *ptr) static void destroy(void *ptr)
{ {
typedef shared_ptr_storage<Type> storage_type; using storage_type = shared_ptr_storage<Type>;
storage_type::unref( storage_type::unref(
static_cast<typename storage_type::storage_type*>(ptr) static_cast<typename storage_type::storage_type*>(ptr)
); );
@ -1477,13 +1446,11 @@ namespace nasal
template<class T> template<class T>
naGhostType naGhostType
Ghost<T, typename boost::enable_if<is_strong_ref<T> >::type> Ghost<T, std::enable_if_t<is_strong_ref<T>::value>>::_ghost_type_strong;
::_ghost_type_strong;
template<class T> template<class T>
naGhostType naGhostType
Ghost<T, typename boost::enable_if<is_strong_ref<T> >::type> Ghost<T, std::enable_if_t<is_strong_ref<T>::value>>::_ghost_type_weak;
::_ghost_type_weak;
} // namespace nasal } // namespace nasal
@ -1492,15 +1459,13 @@ namespace nasal
* Convert every shared pointer to a ghost. * Convert every shared pointer to a ghost.
*/ */
template<class T> template<class T>
typename boost::enable_if< std::enable_if_t<
nasal::internal::has_element_type< nasal::internal::has_element_type<std::remove_cvref_t<T>>::value,
typename nasal::internal::reduced_type<T>::type
>,
naRef naRef
>::type >
to_nasal_helper(naContext c, T ptr) to_nasal_helper(naContext c, T ptr)
{ {
typedef typename nasal::shared_ptr_traits<T>::strong_ref strong_ref; using strong_ref = typename nasal::shared_ptr_traits<T>::strong_ref;
return nasal::Ghost<strong_ref>::makeGhost(c, ptr); return nasal::Ghost<strong_ref>::makeGhost(c, ptr);
} }
@ -1508,15 +1473,13 @@ to_nasal_helper(naContext c, T ptr)
* Convert nasal ghosts/hashes to shared pointer (of a ghost). * Convert nasal ghosts/hashes to shared pointer (of a ghost).
*/ */
template<class T> template<class T>
typename boost::enable_if< std::enable_if_t<
nasal::internal::has_element_type< nasal::internal::has_element_type<std::remove_cvref_t<T>>::value,
typename nasal::internal::reduced_type<T>::type
>,
T T
>::type >
from_nasal_helper(naContext c, naRef ref, const T*) from_nasal_helper(naContext c, naRef ref, const T*)
{ {
typedef typename nasal::shared_ptr_traits<T>::strong_ref strong_ref; using strong_ref = typename nasal::shared_ptr_traits<T>::strong_ref;
return T(nasal::Ghost<strong_ref>::fromNasalChecked(c, ref)); return T(nasal::Ghost<strong_ref>::fromNasalChecked(c, ref));
} }
@ -1524,11 +1487,11 @@ from_nasal_helper(naContext c, naRef ref, const T*)
* Convert any pointer to a SGReferenced based object to a ghost. * Convert any pointer to a SGReferenced based object to a ghost.
*/ */
template<class T> template<class T>
typename boost::enable_if_c< std::enable_if_t<
boost::is_base_of<SGReferenced, T>::value std::is_base_of<SGReferenced, T>::value
|| boost::is_base_of<SGWeakReferenced, T>::value, || std::is_base_of<SGWeakReferenced, T>::value,
naRef naRef
>::type >
to_nasal_helper(naContext c, T* ptr) to_nasal_helper(naContext c, T* ptr)
{ {
return nasal::Ghost<SGSharedPtr<T> >::makeGhost(c, SGSharedPtr<T>(ptr)); return nasal::Ghost<SGSharedPtr<T> >::makeGhost(c, SGSharedPtr<T>(ptr));
@ -1538,20 +1501,14 @@ to_nasal_helper(naContext c, T* ptr)
* Convert nasal ghosts/hashes to pointer (of a SGReferenced based ghost). * Convert nasal ghosts/hashes to pointer (of a SGReferenced based ghost).
*/ */
template<class T> template<class T>
typename boost::enable_if_c< std::enable_if_t<
boost::is_base_of< std::is_base_of<SGReferenced, std::remove_pointer_t<T>>::value
SGReferenced, || std::is_base_of<SGWeakReferenced, std::remove_pointer_t<T>>::value,
typename boost::remove_pointer<T>::type
>::value
|| boost::is_base_of<
SGWeakReferenced,
typename boost::remove_pointer<T>::type
>::value,
T T
>::type >
from_nasal_helper(naContext c, naRef ref, const T*) from_nasal_helper(naContext c, naRef ref, const T*)
{ {
typedef SGSharedPtr<typename boost::remove_pointer<T>::type> TypeRef; using TypeRef = SGSharedPtr<std::remove_pointer_t<T>>;
return T(nasal::Ghost<TypeRef>::fromNasalChecked(c, ref)); return T(nasal::Ghost<TypeRef>::fromNasalChecked(c, ref));
} }
@ -1559,10 +1516,10 @@ from_nasal_helper(naContext c, naRef ref, const T*)
* Convert any pointer to a osg::Referenced based object to a ghost. * Convert any pointer to a osg::Referenced based object to a ghost.
*/ */
template<class T> template<class T>
typename boost::enable_if< std::enable_if_t<
boost::is_base_of<osg::Referenced, T>, std::is_base_of<osg::Referenced, T>::value,
naRef naRef
>::type >
to_nasal_helper(naContext c, T* ptr) to_nasal_helper(naContext c, T* ptr)
{ {
return nasal::Ghost<osg::ref_ptr<T> >::makeGhost(c, osg::ref_ptr<T>(ptr)); return nasal::Ghost<osg::ref_ptr<T> >::makeGhost(c, osg::ref_ptr<T>(ptr));
@ -1572,13 +1529,13 @@ to_nasal_helper(naContext c, T* ptr)
* Convert nasal ghosts/hashes to pointer (of a osg::Referenced based ghost). * Convert nasal ghosts/hashes to pointer (of a osg::Referenced based ghost).
*/ */
template<class T> template<class T>
typename boost::enable_if< std::enable_if_t<
boost::is_base_of<osg::Referenced, typename boost::remove_pointer<T>::type>, std::is_base_of<osg::Referenced, std::remove_pointer_t<T>>::value,
T T
>::type >
from_nasal_helper(naContext c, naRef ref, const T*) from_nasal_helper(naContext c, naRef ref, const T*)
{ {
typedef osg::ref_ptr<typename boost::remove_pointer<T>::type> TypeRef; using TypeRef = osg::ref_ptr<std::remove_pointer_t<T>>;
return T(nasal::Ghost<TypeRef>::fromNasalChecked(c, ref)); return T(nasal::Ghost<TypeRef>::fromNasalChecked(c, ref));
} }

View File

@ -20,10 +20,7 @@
#ifndef SG_NASAL_TRAITS_HXX_ #ifndef SG_NASAL_TRAITS_HXX_
#define SG_NASAL_TRAITS_HXX_ #define SG_NASAL_TRAITS_HXX_
#include <boost/mpl/logical.hpp> #include <simgear/std/type_traits.hxx>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/utility/enable_if.hpp>
// Forward declarations // Forward declarations
class SGReferenced; class SGReferenced;
@ -56,12 +53,11 @@ namespace osg
namespace nasal namespace nasal
{ {
template<class T> template<class T>
struct is_vec2: public boost::integral_constant<bool, false> {}; struct is_vec2: public std::false_type {};
#define SG_MAKE_TRAIT(templ,type,attr)\ #define SG_MAKE_TRAIT(templ,type,attr)\
template templ\ template templ\
struct attr< type >:\ struct attr< type >: public std::true_type {};
public boost::integral_constant<bool, true> {};
SG_MAKE_TRAIT(<class T>, SGVec2<T>, is_vec2) SG_MAKE_TRAIT(<class T>, SGVec2<T>, is_vec2)
SG_MAKE_TRAIT(<>, osg::Vec2b, is_vec2) SG_MAKE_TRAIT(<>, osg::Vec2b, is_vec2)
@ -75,42 +71,34 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
struct shared_ptr_traits; struct shared_ptr_traits;
template<class T> template<class T>
struct is_strong_ref: struct is_strong_ref: public std::false_type {};
public boost::integral_constant<bool, false>
{};
template<class T> template<class T>
struct is_weak_ref: struct is_weak_ref: public std::false_type {};
public boost::integral_constant<bool, false>
{};
#define SG_MAKE_SHARED_PTR_TRAIT(strong, weak, intrusive)\ #define SG_MAKE_SHARED_PTR_TRAIT(strong, weak, intrusive)\
template<class T>\ template<class T>\
struct shared_ptr_traits<strong<T> >\ struct shared_ptr_traits<strong<T> >\
{\ {\
typedef strong<T> strong_ref;\ using strong_ref = strong<T>;\
typedef weak<T> weak_ref;\ using weak_ref = weak<T>;\
typedef T element_type;\ using element_type = T;\
typedef boost::integral_constant<bool, true> is_strong;\ using is_strong = std::true_type;\
typedef boost::integral_constant<bool, intrusive> is_intrusive;\ using is_intrusive = std::bool_constant<intrusive>;\
};\ };\
template<class T>\ template<class T>\
struct shared_ptr_traits<weak<T> >\ struct shared_ptr_traits<weak<T> >\
{\ {\
typedef strong<T> strong_ref;\ using strong_ref = strong<T>;\
typedef weak<T> weak_ref;\ using weak_ref = weak<T>;\
typedef T element_type;\ using element_type = T;\
typedef boost::integral_constant<bool, false> is_strong;\ using is_strong = std::false_type;\
typedef boost::integral_constant<bool, intrusive> is_intrusive;\ using is_intrusive = std::bool_constant<intrusive>;\
};\ };\
template<class T>\ template<class T>\
struct is_strong_ref<strong<T> >:\ struct is_strong_ref<strong<T> >: public std::true_type {};\
public boost::integral_constant<bool, true>\
{};\
template<class T>\ template<class T>\
struct is_weak_ref<weak<T> >:\ struct is_weak_ref<weak<T> >: public std::true_type {};
public boost::integral_constant<bool, true>\
{};
SG_MAKE_SHARED_PTR_TRAIT(SGSharedPtr, SGWeakPtr, true) SG_MAKE_SHARED_PTR_TRAIT(SGSharedPtr, SGWeakPtr, true)
SG_MAKE_SHARED_PTR_TRAIT(osg::ref_ptr, osg::observer_ptr, true) SG_MAKE_SHARED_PTR_TRAIT(osg::ref_ptr, osg::observer_ptr, true)
@ -119,25 +107,20 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
#undef SG_MAKE_SHARED_PTR_TRAIT #undef SG_MAKE_SHARED_PTR_TRAIT
template<class T> template<class T>
struct supports_weak_ref: struct supports_weak_ref: public std::true_type {};
public boost::integral_constant<bool, true>
{};
template<class T> template<class T>
struct supports_weak_ref<SGSharedPtr<T> >: struct supports_weak_ref<SGSharedPtr<T> >:
public boost::integral_constant< public std::bool_constant<std::is_base_of<SGWeakReferenced, T>::value>
bool,
boost::is_base_of<SGWeakReferenced, T>::value
>
{}; {};
template<class T> template<class T>
struct shared_ptr_storage struct shared_ptr_storage
{ {
typedef T storage_type; using storage_type = T;
typedef typename T::element_type element_type; using element_type = typename T::element_type;
typedef typename shared_ptr_traits<T>::strong_ref strong_ref; using strong_ref = typename shared_ptr_traits<T>::strong_ref;
typedef typename shared_ptr_traits<T>::weak_ref weak_ref; using weak_ref = typename shared_ptr_traits<T>::weak_ref;
template<class U> template<class U>
static storage_type* ref(U ptr) static storage_type* ref(U ptr)
@ -151,39 +134,30 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<std::is_same<U, element_type*>::value, element_type*>
boost::is_same<U, element_type*>,
element_type*
>::type
get(storage_type* ptr) get(storage_type* ptr)
{ {
return get_pointer(*ptr); return get_pointer(*ptr);
} }
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<
boost::mpl::or_< std::is_same<U, strong_ref>::value
boost::is_same<U, strong_ref>, || (std::is_same<U, weak_ref>::value && supports_weak_ref<U>::value),
boost::mpl::and_<
boost::is_same<U, weak_ref>,
supports_weak_ref<U>
>
>,
U U
>::type >
get(storage_type* ptr) get(storage_type* ptr)
{ {
return U(*ptr); return U(*ptr);
} }
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<
boost::mpl::and_< std::is_same<U, weak_ref>::value && !supports_weak_ref<U>::value,
boost::is_same<U, weak_ref>,
boost::mpl::not_<supports_weak_ref<U> >
>,
U U
>::type >
get(storage_type* ptr) get(storage_type* ptr)
{ {
return U(); return U();
@ -195,46 +169,37 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
template<class T> template<class T>
struct intrusive_ptr_storage struct intrusive_ptr_storage
{ {
typedef typename T::element_type storage_type; using storage_type = typename T::element_type;
typedef typename T::element_type element_type; using element_type = typename T::element_type;
typedef typename shared_ptr_traits<T>::strong_ref strong_ref; using strong_ref = typename shared_ptr_traits<T>::strong_ref;
typedef typename shared_ptr_traits<T>::weak_ref weak_ref; using weak_ref = typename shared_ptr_traits<T>::weak_ref;
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<std::is_same<U, element_type*>::value, element_type*>
boost::is_same<U, element_type*>,
element_type*
>::type
get(storage_type* ptr) get(storage_type* ptr)
{ {
return ptr; return ptr;
} }
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<
boost::mpl::or_< std::is_same<U, strong_ref>::value
boost::is_same<U, strong_ref>, || (std::is_same<U, weak_ref>::value && supports_weak_ref<U>::value),
boost::mpl::and_<
boost::is_same<U, weak_ref>,
supports_weak_ref<U>
>
>,
U U
>::type >
get(storage_type* ptr) get(storage_type* ptr)
{ {
return U(ptr); return U(ptr);
} }
template<class U> template<class U>
static static
typename boost::enable_if< std::enable_if_t<
boost::mpl::and_< std::is_same<U, weak_ref>::value && !supports_weak_ref<U>::value,
boost::is_same<U, weak_ref>,
boost::mpl::not_<supports_weak_ref<U> >
>,
U U
>::type >
get(storage_type* ptr) get(storage_type* ptr)
{ {
return U(); return U();
@ -246,8 +211,8 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
struct shared_ptr_storage<SGSharedPtr<T> >: struct shared_ptr_storage<SGSharedPtr<T> >:
public internal::intrusive_ptr_storage<SGSharedPtr<T> > public internal::intrusive_ptr_storage<SGSharedPtr<T> >
{ {
typedef T storage_type; using storage_type = T;
typedef T element_type; using element_type = T;
static storage_type* ref(element_type* ptr) static storage_type* ref(element_type* ptr)
{ {
@ -265,8 +230,8 @@ SG_MAKE_TRAIT(<>, osg::Vec2s, is_vec2)
struct shared_ptr_storage<osg::ref_ptr<T> >: struct shared_ptr_storage<osg::ref_ptr<T> >:
public internal::intrusive_ptr_storage<osg::ref_ptr<T> > public internal::intrusive_ptr_storage<osg::ref_ptr<T> >
{ {
typedef T storage_type; using storage_type = T;
typedef T element_type; using element_type = T;
static storage_type* ref(element_type* ptr) static storage_type* ref(element_type* ptr)

View File

@ -16,6 +16,10 @@
#cmakedefine HAVE_MKDTEMP #cmakedefine HAVE_MKDTEMP
#cmakedefine HAVE_AL_EXT_H #cmakedefine HAVE_AL_EXT_H
#cmakedefine HAVE_STD_INDEX_SEQUENCE #cmakedefine HAVE_STD_INDEX_SEQUENCE
#cmakedefine HAVE_STD_REMOVE_CV_T
#cmakedefine HAVE_STD_REMOVE_CVREF_T
#cmakedefine HAVE_STD_ENABLE_IF_T
#cmakedefine HAVE_STD_BOOL_CONSTANT
#cmakedefine GCC_ATOMIC_BUILTINS_FOUND #cmakedefine GCC_ATOMIC_BUILTINS_FOUND

View File

@ -0,0 +1,21 @@
include (SimGearComponent)
set(HEADERS
integer_sequence.hxx
type_traits.hxx
)
set(SOURCES
)
simgear_component(std std "${SOURCES}" "${HEADERS}")
if(ENABLE_TESTS)
add_executable(test_integer_sequence integer_sequence_test.cxx)
add_test(integer_sequence ${EXECUTABLE_OUTPUT_PATH}/test_integer_sequence)
target_link_libraries(test_integer_sequence ${TEST_LIBS})
add_executable(test_type_traits type_traits_test.cxx)
add_test(type_traits ${EXECUTABLE_OUTPUT_PATH}/test_type_traits)
target_link_libraries(test_type_traits ${TEST_LIBS})
endif()

View File

@ -17,13 +17,13 @@
// License along with this library; if not, write to the Free Software // License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#ifndef SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ #ifndef SIMGEAR_STD_INTEGER_SEQUENCE_HXX_
#define SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ #define SIMGEAR_STD_INTEGER_SEQUENCE_HXX_
#include <simgear/simgear_config.h> #include <simgear/simgear_config.h>
#include "type_traits.hxx"
#include <utility> #include <utility>
#include <type_traits>
#ifndef HAVE_STD_INDEX_SEQUENCE #ifndef HAVE_STD_INDEX_SEQUENCE
# include <cstddef> # include <cstddef>
@ -85,4 +85,4 @@ namespace std
} }
#endif #endif
#endif /* SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_ */ #endif /* SIMGEAR_STD_INTEGER_SEQUENCE_HXX_ */

View File

@ -1,5 +1,4 @@
#include "integer_sequence.hxx" #include <simgear/std/integer_sequence.hxx>
#include <iostream> #include <iostream>
template<class T> template<class T>

View File

@ -0,0 +1,67 @@
///@file
/// Type Traits (Provide features of later C++ standards)
//
// Copyright (C) 2017 Thomas Geymayer <tomgey@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#ifndef SIMGEAR_STD_TYPE_TRAITS_HXX_
#define SIMGEAR_STD_TYPE_TRAITS_HXX_
#include <simgear/simgear_config.h>
#include <type_traits>
namespace std
{
#ifndef HAVE_STD_REMOVE_CV_T
template<class T>
using remove_cv_t = typename remove_cv<T>::type;
template<class T>
using remove_const_t = typename remove_const<T>::type;
template<class T>
using remove_volatile_t = typename remove_volatile<T>::type;
template<class T>
using remove_reference_t = typename remove_reference<T>::type;
template< class T >
using remove_pointer_t = typename remove_pointer<T>::type;
#endif
#ifndef HAVE_STD_REMOVE_CVREF_T
template<class T>
struct remove_cvref
{
using type = remove_cv_t<remove_reference_t<T>>;
};
template<class T>
using remove_cvref_t = typename remove_cvref<T>::type;
#endif
#ifndef HAVE_STD_ENABLE_IF_T
template<bool B, class T = void>
using enable_if_t = typename enable_if<B, T>::type;
#endif
#ifndef HAVE_STD_BOOL_CONSTANT
template <bool B>
using bool_constant = integral_constant<bool, B>;
#endif
}
#endif /* SIMGEAR_STD_TYPE_TRAITS_HXX_ */

View File

@ -0,0 +1,24 @@
#include <simgear/std/type_traits.hxx>
using namespace std;
template<class T, class U>
void assert_same()
{
static_assert(is_same<T, U>::value, "");
}
int main(int argc, char* argv[])
{
assert_same<remove_cv_t<int const volatile>, int>();
assert_same<remove_const_t<int const volatile>, int volatile>();
assert_same<remove_volatile_t<int const volatile>, int const>();
assert_same<remove_reference_t<int const volatile&>, int const volatile>();
assert_same<remove_pointer_t<int const volatile*>, int const volatile>();
assert_same<remove_cvref_t<int const volatile&>, int>();
assert_same<enable_if_t<true, double>, double>();
assert_same<bool_constant<true>, integral_constant<bool, true>>();
return 0;
}