You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							183 lines
						
					
					
						
							7.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							183 lines
						
					
					
						
							7.5 KiB
						
					
					
				| /* | |
|     pybind11/descr.h: Helper type for concatenating type signatures | |
|     either at runtime (C++11) or compile time (C++14) | |
|  | |
|     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> | |
|  | |
|     All rights reserved. Use of this source code is governed by a | |
|     BSD-style license that can be found in the LICENSE file. | |
| */ | |
| 
 | |
| #pragma once | |
|  | |
| #include "common.h" | |
|  | |
| NAMESPACE_BEGIN(pybind11) | |
| NAMESPACE_BEGIN(detail) | |
| 
 | |
| #if defined(PYBIND11_CPP14) /* Concatenate type signatures at compile time using C++14 */ | |
|  | |
| template <size_t Size1, size_t Size2> class descr { | |
|     template <size_t Size1_, size_t Size2_> friend class descr; | |
| public: | |
|     constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) | |
|         : descr(text, types, | |
|                 make_index_sequence<Size1>(), | |
|                 make_index_sequence<Size2>()) { } | |
| 
 | |
|     constexpr const char *text() const { return m_text; } | |
|     constexpr const std::type_info * const * types() const { return m_types; } | |
| 
 | |
|     template <size_t OtherSize1, size_t OtherSize2> | |
|     constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> operator+(const descr<OtherSize1, OtherSize2> &other) const { | |
|         return concat(other, | |
|                       make_index_sequence<Size1>(), | |
|                       make_index_sequence<Size2>(), | |
|                       make_index_sequence<OtherSize1>(), | |
|                       make_index_sequence<OtherSize2>()); | |
|     } | |
| 
 | |
| protected: | |
|     template <size_t... Indices1, size_t... Indices2> | |
|     constexpr descr( | |
|         char const (&text) [Size1+1], | |
|         const std::type_info * const (&types) [Size2+1], | |
|         index_sequence<Indices1...>, index_sequence<Indices2...>) | |
|         : m_text{text[Indices1]..., '\0'}, | |
|           m_types{types[Indices2]...,  nullptr } {} | |
| 
 | |
|     template <size_t OtherSize1, size_t OtherSize2, size_t... Indices1, | |
|               size_t... Indices2, size_t... OtherIndices1, size_t... OtherIndices2> | |
|     constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> | |
|     concat(const descr<OtherSize1, OtherSize2> &other, | |
|            index_sequence<Indices1...>, index_sequence<Indices2...>, | |
|            index_sequence<OtherIndices1...>, index_sequence<OtherIndices2...>) const { | |
|         return descr<Size1 + OtherSize1, Size2 + OtherSize2>( | |
|             { m_text[Indices1]..., other.m_text[OtherIndices1]..., '\0' }, | |
|             { m_types[Indices2]..., other.m_types[OtherIndices2]..., nullptr } | |
|         ); | |
|     } | |
| 
 | |
| protected: | |
|     char m_text[Size1 + 1]; | |
|     const std::type_info * m_types[Size2 + 1]; | |
| }; | |
| 
 | |
| template <size_t Size> constexpr descr<Size - 1, 0> _(char const(&text)[Size]) { | |
|     return descr<Size - 1, 0>(text, { nullptr }); | |
| } | |
| 
 | |
| template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; | |
| template <size_t...Digits> struct int_to_str<0, Digits...> { | |
|     static constexpr auto digits = descr<sizeof...(Digits), 0>({ ('0' + Digits)..., '\0' }, { nullptr }); | |
| }; | |
| 
 | |
| // Ternary description (like std::conditional) | |
| template <bool B, size_t Size1, size_t Size2> | |
| constexpr enable_if_t<B, descr<Size1 - 1, 0>> _(char const(&text1)[Size1], char const(&)[Size2]) { | |
|     return _(text1); | |
| } | |
| template <bool B, size_t Size1, size_t Size2> | |
| constexpr enable_if_t<!B, descr<Size2 - 1, 0>> _(char const(&)[Size1], char const(&text2)[Size2]) { | |
|     return _(text2); | |
| } | |
| template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> | |
| constexpr enable_if_t<B, descr<SizeA1, SizeA2>> _(descr<SizeA1, SizeA2> d, descr<SizeB1, SizeB2>) { return d; } | |
| template <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> | |
| constexpr enable_if_t<!B, descr<SizeB1, SizeB2>> _(descr<SizeA1, SizeA2>, descr<SizeB1, SizeB2> d) { return d; } | |
| 
 | |
| template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) { | |
|     return int_to_str<Size / 10, Size % 10>::digits; | |
| } | |
| 
 | |
| template <typename Type> constexpr descr<1, 1> _() { | |
|     return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); | |
| } | |
| 
 | |
| inline constexpr descr<0, 0> concat() { return _(""); } | |
| template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr) { return descr; } | |
| template <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr, Args&&... args) { return descr + _(", ") + concat(args...); } | |
| template <size_t Size1, size_t Size2> auto constexpr type_descr(descr<Size1, Size2> descr) { return _("{") + descr + _("}"); } | |
| 
 | |
| #define PYBIND11_DESCR constexpr auto | |
|  | |
| #else /* Simpler C++11 implementation based on run-time memory allocation and copying */ | |
|  | |
| class descr { | |
| public: | |
|     PYBIND11_NOINLINE descr(const char *text, const std::type_info * const * types) { | |
|         size_t nChars = len(text), nTypes = len(types); | |
|         m_text  = new char[nChars]; | |
|         m_types = new const std::type_info *[nTypes]; | |
|         memcpy(m_text, text, nChars * sizeof(char)); | |
|         memcpy(m_types, types, nTypes * sizeof(const std::type_info *)); | |
|     } | |
| 
 | |
|     PYBIND11_NOINLINE descr friend operator+(descr &&d1, descr &&d2) { | |
|         descr r; | |
| 
 | |
|         size_t nChars1 = len(d1.m_text), nTypes1 = len(d1.m_types); | |
|         size_t nChars2 = len(d2.m_text), nTypes2 = len(d2.m_types); | |
| 
 | |
|         r.m_text  = new char[nChars1 + nChars2 - 1]; | |
|         r.m_types = new const std::type_info *[nTypes1 + nTypes2 - 1]; | |
|         memcpy(r.m_text, d1.m_text, (nChars1-1) * sizeof(char)); | |
|         memcpy(r.m_text + nChars1 - 1, d2.m_text, nChars2 * sizeof(char)); | |
|         memcpy(r.m_types, d1.m_types, (nTypes1-1) * sizeof(std::type_info *)); | |
|         memcpy(r.m_types + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *)); | |
| 
 | |
|         delete[] d1.m_text; delete[] d1.m_types; | |
|         delete[] d2.m_text; delete[] d2.m_types; | |
| 
 | |
|         return r; | |
|     } | |
| 
 | |
|     char *text() { return m_text; } | |
|     const std::type_info * * types() { return m_types; } | |
| 
 | |
| protected: | |
|     PYBIND11_NOINLINE descr() { } | |
| 
 | |
|     template <typename T> static size_t len(const T *ptr) { // return length including null termination | |
|         const T *it = ptr; | |
|         while (*it++ != (T) 0) | |
|             ; | |
|         return static_cast<size_t>(it - ptr); | |
|     } | |
| 
 | |
|     const std::type_info **m_types = nullptr; | |
|     char *m_text = nullptr; | |
| }; | |
| 
 | |
| /* The 'PYBIND11_NOINLINE inline' combinations below are intentional to get the desired linkage while producing as little object code as possible */ | |
| 
 | |
| PYBIND11_NOINLINE inline descr _(const char *text) { | |
|     const std::type_info *types[1] = { nullptr }; | |
|     return descr(text, types); | |
| } | |
| 
 | |
| template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(const char *text1, const char *) { return _(text1); } | |
| template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(char const *, const char *text2) { return _(text2); } | |
| template <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(descr d, descr) { return d; } | |
| template <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(descr, descr d) { return d; } | |
| 
 | |
| template <typename Type> PYBIND11_NOINLINE descr _() { | |
|     const std::type_info *types[2] = { &typeid(Type), nullptr }; | |
|     return descr("%", types); | |
| } | |
| 
 | |
| template <size_t Size> PYBIND11_NOINLINE descr _() { | |
|     const std::type_info *types[1] = { nullptr }; | |
|     return descr(std::to_string(Size).c_str(), types); | |
| } | |
| 
 | |
| PYBIND11_NOINLINE inline descr concat() { return _(""); } | |
| PYBIND11_NOINLINE inline descr concat(descr &&d) { return d; } | |
| template <typename... Args> PYBIND11_NOINLINE descr concat(descr &&d, Args&&... args) { return std::move(d) + _(", ") + concat(std::forward<Args>(args)...); } | |
| PYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move(d) + _("}"); } | |
| 
 | |
| #define PYBIND11_DESCR ::pybind11::detail::descr | |
| #endif | |
|  | |
| NAMESPACE_END(detail) | |
| NAMESPACE_END(pybind11)
 |