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_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
check_cxx_source_compiles("
#include <utility>
#include <type_traits>
std::make_index_sequence<0> t;
int main() { return 0; }"
HAVE_STD_INDEX_SEQUENCE
)
include(CheckCXXFeatures)
# use BEFORE to ensure local directories are used first,
# 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
props
serial
std
structure
threads
timing

View File

@ -9,7 +9,6 @@ set(HEADERS
SVGpreserveAspectRatio.hxx
argparse.hxx
interpolator.hxx
integer_sequence.hxx
make_new.hxx
sg_dir.hxx
sg_hash.hxx
@ -57,10 +56,6 @@ add_executable(test_CSSBorder CSSBorder_test.cxx)
add_test(CSSBorder ${EXECUTABLE_OUTPUT_PATH}/test_CSSBorder)
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_test(tabbed_values ${EXECUTABLE_OUTPUT_PATH}/test_tabbed_values)
target_link_libraries(test_tabbed_values ${TEST_LIBS})

View File

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

View File

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

View File

@ -16,6 +16,10 @@
#cmakedefine HAVE_MKDTEMP
#cmakedefine HAVE_AL_EXT_H
#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

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
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#ifndef SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_
#define SIMGEAR_MISC_INTEGER_SEQUENCE_HXX_
#ifndef SIMGEAR_STD_INTEGER_SEQUENCE_HXX_
#define SIMGEAR_STD_INTEGER_SEQUENCE_HXX_
#include <simgear/simgear_config.h>
#include "type_traits.hxx"
#include <utility>
#include <type_traits>
#ifndef HAVE_STD_INDEX_SEQUENCE
# include <cstddef>
@ -85,4 +85,4 @@ namespace std
}
#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>
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;
}