descr.h revision 12391
112391Sjason@lowepower.com/* 212391Sjason@lowepower.com pybind11/detail/descr.h: Helper type for concatenating type signatures 312391Sjason@lowepower.com either at runtime (C++11) or compile time (C++14) 412391Sjason@lowepower.com 512391Sjason@lowepower.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 612391Sjason@lowepower.com 712391Sjason@lowepower.com All rights reserved. Use of this source code is governed by a 812391Sjason@lowepower.com BSD-style license that can be found in the LICENSE file. 912391Sjason@lowepower.com*/ 1012391Sjason@lowepower.com 1112391Sjason@lowepower.com#pragma once 1212391Sjason@lowepower.com 1312391Sjason@lowepower.com#include "common.h" 1412391Sjason@lowepower.com 1512391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 1612391Sjason@lowepower.comNAMESPACE_BEGIN(detail) 1712391Sjason@lowepower.com 1812391Sjason@lowepower.com/* Concatenate type signatures at compile time using C++14 */ 1912391Sjason@lowepower.com#if defined(PYBIND11_CPP14) && !defined(_MSC_VER) 2012391Sjason@lowepower.com#define PYBIND11_CONSTEXPR_DESCR 2112391Sjason@lowepower.com 2212391Sjason@lowepower.comtemplate <size_t Size1, size_t Size2> class descr { 2312391Sjason@lowepower.com template <size_t Size1_, size_t Size2_> friend class descr; 2412391Sjason@lowepower.compublic: 2512391Sjason@lowepower.com constexpr descr(char const (&text) [Size1+1], const std::type_info * const (&types)[Size2+1]) 2612391Sjason@lowepower.com : descr(text, types, 2712391Sjason@lowepower.com make_index_sequence<Size1>(), 2812391Sjason@lowepower.com make_index_sequence<Size2>()) { } 2912391Sjason@lowepower.com 3012391Sjason@lowepower.com constexpr const char *text() const { return m_text; } 3112391Sjason@lowepower.com constexpr const std::type_info * const * types() const { return m_types; } 3212391Sjason@lowepower.com 3312391Sjason@lowepower.com template <size_t OtherSize1, size_t OtherSize2> 3412391Sjason@lowepower.com constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> operator+(const descr<OtherSize1, OtherSize2> &other) const { 3512391Sjason@lowepower.com return concat(other, 3612391Sjason@lowepower.com make_index_sequence<Size1>(), 3712391Sjason@lowepower.com make_index_sequence<Size2>(), 3812391Sjason@lowepower.com make_index_sequence<OtherSize1>(), 3912391Sjason@lowepower.com make_index_sequence<OtherSize2>()); 4012391Sjason@lowepower.com } 4112391Sjason@lowepower.com 4212391Sjason@lowepower.comprotected: 4312391Sjason@lowepower.com template <size_t... Indices1, size_t... Indices2> 4412391Sjason@lowepower.com constexpr descr( 4512391Sjason@lowepower.com char const (&text) [Size1+1], 4612391Sjason@lowepower.com const std::type_info * const (&types) [Size2+1], 4712391Sjason@lowepower.com index_sequence<Indices1...>, index_sequence<Indices2...>) 4812391Sjason@lowepower.com : m_text{text[Indices1]..., '\0'}, 4912391Sjason@lowepower.com m_types{types[Indices2]..., nullptr } {} 5012391Sjason@lowepower.com 5112391Sjason@lowepower.com template <size_t OtherSize1, size_t OtherSize2, size_t... Indices1, 5212391Sjason@lowepower.com size_t... Indices2, size_t... OtherIndices1, size_t... OtherIndices2> 5312391Sjason@lowepower.com constexpr descr<Size1 + OtherSize1, Size2 + OtherSize2> 5412391Sjason@lowepower.com concat(const descr<OtherSize1, OtherSize2> &other, 5512391Sjason@lowepower.com index_sequence<Indices1...>, index_sequence<Indices2...>, 5612391Sjason@lowepower.com index_sequence<OtherIndices1...>, index_sequence<OtherIndices2...>) const { 5712391Sjason@lowepower.com return descr<Size1 + OtherSize1, Size2 + OtherSize2>( 5812391Sjason@lowepower.com { m_text[Indices1]..., other.m_text[OtherIndices1]..., '\0' }, 5912391Sjason@lowepower.com { m_types[Indices2]..., other.m_types[OtherIndices2]..., nullptr } 6012391Sjason@lowepower.com ); 6112391Sjason@lowepower.com } 6212391Sjason@lowepower.com 6312391Sjason@lowepower.comprotected: 6412391Sjason@lowepower.com char m_text[Size1 + 1]; 6512391Sjason@lowepower.com const std::type_info * m_types[Size2 + 1]; 6612391Sjason@lowepower.com}; 6712391Sjason@lowepower.com 6812391Sjason@lowepower.comtemplate <size_t Size> constexpr descr<Size - 1, 0> _(char const(&text)[Size]) { 6912391Sjason@lowepower.com return descr<Size - 1, 0>(text, { nullptr }); 7012391Sjason@lowepower.com} 7112391Sjason@lowepower.com 7212391Sjason@lowepower.comtemplate <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; 7312391Sjason@lowepower.comtemplate <size_t...Digits> struct int_to_str<0, Digits...> { 7412391Sjason@lowepower.com static constexpr auto digits = descr<sizeof...(Digits), 0>({ ('0' + Digits)..., '\0' }, { nullptr }); 7512391Sjason@lowepower.com}; 7612391Sjason@lowepower.com 7712391Sjason@lowepower.com// Ternary description (like std::conditional) 7812391Sjason@lowepower.comtemplate <bool B, size_t Size1, size_t Size2> 7912391Sjason@lowepower.comconstexpr enable_if_t<B, descr<Size1 - 1, 0>> _(char const(&text1)[Size1], char const(&)[Size2]) { 8012391Sjason@lowepower.com return _(text1); 8112391Sjason@lowepower.com} 8212391Sjason@lowepower.comtemplate <bool B, size_t Size1, size_t Size2> 8312391Sjason@lowepower.comconstexpr enable_if_t<!B, descr<Size2 - 1, 0>> _(char const(&)[Size1], char const(&text2)[Size2]) { 8412391Sjason@lowepower.com return _(text2); 8512391Sjason@lowepower.com} 8612391Sjason@lowepower.comtemplate <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> 8712391Sjason@lowepower.comconstexpr enable_if_t<B, descr<SizeA1, SizeA2>> _(descr<SizeA1, SizeA2> d, descr<SizeB1, SizeB2>) { return d; } 8812391Sjason@lowepower.comtemplate <bool B, size_t SizeA1, size_t SizeA2, size_t SizeB1, size_t SizeB2> 8912391Sjason@lowepower.comconstexpr enable_if_t<!B, descr<SizeB1, SizeB2>> _(descr<SizeA1, SizeA2>, descr<SizeB1, SizeB2> d) { return d; } 9012391Sjason@lowepower.com 9112391Sjason@lowepower.comtemplate <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) { 9212391Sjason@lowepower.com return int_to_str<Size / 10, Size % 10>::digits; 9312391Sjason@lowepower.com} 9412391Sjason@lowepower.com 9512391Sjason@lowepower.comtemplate <typename Type> constexpr descr<1, 1> _() { 9612391Sjason@lowepower.com return descr<1, 1>({ '%', '\0' }, { &typeid(Type), nullptr }); 9712391Sjason@lowepower.com} 9812391Sjason@lowepower.com 9912391Sjason@lowepower.cominline constexpr descr<0, 0> concat() { return _(""); } 10012391Sjason@lowepower.comtemplate <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr) { return descr; } 10112391Sjason@lowepower.comtemplate <size_t Size1, size_t Size2, typename... Args> auto constexpr concat(descr<Size1, Size2> descr, Args&&... args) { return descr + _(", ") + concat(args...); } 10212391Sjason@lowepower.comtemplate <size_t Size1, size_t Size2> auto constexpr type_descr(descr<Size1, Size2> descr) { return _("{") + descr + _("}"); } 10312391Sjason@lowepower.com 10412391Sjason@lowepower.com#define PYBIND11_DESCR constexpr auto 10512391Sjason@lowepower.com 10612391Sjason@lowepower.com#else /* Simpler C++11 implementation based on run-time memory allocation and copying */ 10712391Sjason@lowepower.com 10812391Sjason@lowepower.comclass descr { 10912391Sjason@lowepower.compublic: 11012391Sjason@lowepower.com PYBIND11_NOINLINE descr(const char *text, const std::type_info * const * types) { 11112391Sjason@lowepower.com size_t nChars = len(text), nTypes = len(types); 11212391Sjason@lowepower.com m_text = new char[nChars]; 11312391Sjason@lowepower.com m_types = new const std::type_info *[nTypes]; 11412391Sjason@lowepower.com memcpy(m_text, text, nChars * sizeof(char)); 11512391Sjason@lowepower.com memcpy(m_types, types, nTypes * sizeof(const std::type_info *)); 11612391Sjason@lowepower.com } 11712391Sjason@lowepower.com 11812391Sjason@lowepower.com PYBIND11_NOINLINE descr operator+(descr &&d2) && { 11912391Sjason@lowepower.com descr r; 12012391Sjason@lowepower.com 12112391Sjason@lowepower.com size_t nChars1 = len(m_text), nTypes1 = len(m_types); 12212391Sjason@lowepower.com size_t nChars2 = len(d2.m_text), nTypes2 = len(d2.m_types); 12312391Sjason@lowepower.com 12412391Sjason@lowepower.com r.m_text = new char[nChars1 + nChars2 - 1]; 12512391Sjason@lowepower.com r.m_types = new const std::type_info *[nTypes1 + nTypes2 - 1]; 12612391Sjason@lowepower.com memcpy(r.m_text, m_text, (nChars1-1) * sizeof(char)); 12712391Sjason@lowepower.com memcpy(r.m_text + nChars1 - 1, d2.m_text, nChars2 * sizeof(char)); 12812391Sjason@lowepower.com memcpy(r.m_types, m_types, (nTypes1-1) * sizeof(std::type_info *)); 12912391Sjason@lowepower.com memcpy(r.m_types + nTypes1 - 1, d2.m_types, nTypes2 * sizeof(std::type_info *)); 13012391Sjason@lowepower.com 13112391Sjason@lowepower.com delete[] m_text; delete[] m_types; 13212391Sjason@lowepower.com delete[] d2.m_text; delete[] d2.m_types; 13312391Sjason@lowepower.com 13412391Sjason@lowepower.com return r; 13512391Sjason@lowepower.com } 13612391Sjason@lowepower.com 13712391Sjason@lowepower.com char *text() { return m_text; } 13812391Sjason@lowepower.com const std::type_info * * types() { return m_types; } 13912391Sjason@lowepower.com 14012391Sjason@lowepower.comprotected: 14112391Sjason@lowepower.com PYBIND11_NOINLINE descr() { } 14212391Sjason@lowepower.com 14312391Sjason@lowepower.com template <typename T> static size_t len(const T *ptr) { // return length including null termination 14412391Sjason@lowepower.com const T *it = ptr; 14512391Sjason@lowepower.com while (*it++ != (T) 0) 14612391Sjason@lowepower.com ; 14712391Sjason@lowepower.com return static_cast<size_t>(it - ptr); 14812391Sjason@lowepower.com } 14912391Sjason@lowepower.com 15012391Sjason@lowepower.com const std::type_info **m_types = nullptr; 15112391Sjason@lowepower.com char *m_text = nullptr; 15212391Sjason@lowepower.com}; 15312391Sjason@lowepower.com 15412391Sjason@lowepower.com/* The 'PYBIND11_NOINLINE inline' combinations below are intentional to get the desired linkage while producing as little object code as possible */ 15512391Sjason@lowepower.com 15612391Sjason@lowepower.comPYBIND11_NOINLINE inline descr _(const char *text) { 15712391Sjason@lowepower.com const std::type_info *types[1] = { nullptr }; 15812391Sjason@lowepower.com return descr(text, types); 15912391Sjason@lowepower.com} 16012391Sjason@lowepower.com 16112391Sjason@lowepower.comtemplate <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(const char *text1, const char *) { return _(text1); } 16212391Sjason@lowepower.comtemplate <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(char const *, const char *text2) { return _(text2); } 16312391Sjason@lowepower.comtemplate <bool B> PYBIND11_NOINLINE enable_if_t<B, descr> _(descr d, descr) { return d; } 16412391Sjason@lowepower.comtemplate <bool B> PYBIND11_NOINLINE enable_if_t<!B, descr> _(descr, descr d) { return d; } 16512391Sjason@lowepower.com 16612391Sjason@lowepower.comtemplate <typename Type> PYBIND11_NOINLINE descr _() { 16712391Sjason@lowepower.com const std::type_info *types[2] = { &typeid(Type), nullptr }; 16812391Sjason@lowepower.com return descr("%", types); 16912391Sjason@lowepower.com} 17012391Sjason@lowepower.com 17112391Sjason@lowepower.comtemplate <size_t Size> PYBIND11_NOINLINE descr _() { 17212391Sjason@lowepower.com const std::type_info *types[1] = { nullptr }; 17312391Sjason@lowepower.com return descr(std::to_string(Size).c_str(), types); 17412391Sjason@lowepower.com} 17512391Sjason@lowepower.com 17612391Sjason@lowepower.comPYBIND11_NOINLINE inline descr concat() { return _(""); } 17712391Sjason@lowepower.comPYBIND11_NOINLINE inline descr concat(descr &&d) { return d; } 17812391Sjason@lowepower.comtemplate <typename... Args> PYBIND11_NOINLINE descr concat(descr &&d, Args&&... args) { return std::move(d) + _(", ") + concat(std::forward<Args>(args)...); } 17912391Sjason@lowepower.comPYBIND11_NOINLINE inline descr type_descr(descr&& d) { return _("{") + std::move(d) + _("}"); } 18012391Sjason@lowepower.com 18112391Sjason@lowepower.com#define PYBIND11_DESCR ::pybind11::detail::descr 18212391Sjason@lowepower.com#endif 18312391Sjason@lowepower.com 18412391Sjason@lowepower.comNAMESPACE_END(detail) 18512391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE) 186