1/* 2 pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time 3 4 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 5 6 All rights reserved. Use of this source code is governed by a 7 BSD-style license that can be found in the LICENSE file. 8*/ 9 10#pragma once 11 12#include "common.h" 13 14NAMESPACE_BEGIN(PYBIND11_NAMESPACE) 15NAMESPACE_BEGIN(detail) 16 17#if !defined(_MSC_VER) 18# define PYBIND11_DESCR_CONSTEXPR static constexpr 19#else 20# define PYBIND11_DESCR_CONSTEXPR const 21#endif 22 23/* Concatenate type signatures at compile time */ 24template <size_t N, typename... Ts> 25struct descr { 26 char text[N + 1]; 27 28 constexpr descr() : text{'\0'} { } 29 constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { } 30 31 template <size_t... Is> 32 constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { } 33 34 template <typename... Chars> 35 constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { } 36 37 static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() { 38 return {{&typeid(Ts)..., nullptr}}; 39 } 40}; 41 42template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2> 43constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b, 44 index_sequence<Is1...>, index_sequence<Is2...>) { 45 return {a.text[Is1]..., b.text[Is2]...}; 46} 47 48template <size_t N1, size_t N2, typename... Ts1, typename... Ts2> 49constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) { 50 return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>()); 51} 52 53template <size_t N> 54constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); } 55constexpr descr<0> _(char const(&)[1]) { return {}; } 56 57template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { }; 58template <size_t...Digits> struct int_to_str<0, Digits...> { 59 static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...); 60}; 61 62// Ternary description (like std::conditional) 63template <bool B, size_t N1, size_t N2> 64constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) { 65 return _(text1); 66} 67template <bool B, size_t N1, size_t N2> 68constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) { 69 return _(text2); 70} 71 72template <bool B, typename T1, typename T2> 73constexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; } 74template <bool B, typename T1, typename T2> 75constexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; } 76 77template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) { 78 return int_to_str<Size / 10, Size % 10>::digits; 79} 80 81template <typename Type> constexpr descr<1, Type> _() { return {'%'}; } 82 83constexpr descr<0> concat() { return {}; } 84 85template <size_t N, typename... Ts> 86constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; } 87 88template <size_t N, typename... Ts, typename... Args> 89constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) 90 -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) { 91 return d + _(", ") + concat(args...); 92} 93 94template <size_t N, typename... Ts> 95constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) { 96 return _("{") + descr + _("}"); 97} 98 99NAMESPACE_END(detail) 100NAMESPACE_END(PYBIND11_NAMESPACE) 101