112391Sjason@lowepower.com/*
214299Sbbruce@ucdavis.edu    pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
312391Sjason@lowepower.com
412391Sjason@lowepower.com    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
512391Sjason@lowepower.com
612391Sjason@lowepower.com    All rights reserved. Use of this source code is governed by a
712391Sjason@lowepower.com    BSD-style license that can be found in the LICENSE file.
812391Sjason@lowepower.com*/
912391Sjason@lowepower.com
1012391Sjason@lowepower.com#pragma once
1112391Sjason@lowepower.com
1212391Sjason@lowepower.com#include "common.h"
1312391Sjason@lowepower.com
1412391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1512391Sjason@lowepower.comNAMESPACE_BEGIN(detail)
1612391Sjason@lowepower.com
1714299Sbbruce@ucdavis.edu#if !defined(_MSC_VER)
1814299Sbbruce@ucdavis.edu#  define PYBIND11_DESCR_CONSTEXPR static constexpr
1914299Sbbruce@ucdavis.edu#else
2014299Sbbruce@ucdavis.edu#  define PYBIND11_DESCR_CONSTEXPR const
2114299Sbbruce@ucdavis.edu#endif
2212391Sjason@lowepower.com
2314299Sbbruce@ucdavis.edu/* Concatenate type signatures at compile time */
2414299Sbbruce@ucdavis.edutemplate <size_t N, typename... Ts>
2514299Sbbruce@ucdavis.edustruct descr {
2614299Sbbruce@ucdavis.edu    char text[N + 1];
2712391Sjason@lowepower.com
2814299Sbbruce@ucdavis.edu    constexpr descr() : text{'\0'} { }
2914299Sbbruce@ucdavis.edu    constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { }
3012391Sjason@lowepower.com
3114299Sbbruce@ucdavis.edu    template <size_t... Is>
3214299Sbbruce@ucdavis.edu    constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { }
3314299Sbbruce@ucdavis.edu
3414299Sbbruce@ucdavis.edu    template <typename... Chars>
3514299Sbbruce@ucdavis.edu    constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { }
3614299Sbbruce@ucdavis.edu
3714299Sbbruce@ucdavis.edu    static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
3814299Sbbruce@ucdavis.edu        return {{&typeid(Ts)..., nullptr}};
3912391Sjason@lowepower.com    }
4012391Sjason@lowepower.com};
4112391Sjason@lowepower.com
4214299Sbbruce@ucdavis.edutemplate <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
4314299Sbbruce@ucdavis.educonstexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b,
4414299Sbbruce@ucdavis.edu                                                   index_sequence<Is1...>, index_sequence<Is2...>) {
4514299Sbbruce@ucdavis.edu    return {a.text[Is1]..., b.text[Is2]...};
4612391Sjason@lowepower.com}
4712391Sjason@lowepower.com
4814299Sbbruce@ucdavis.edutemplate <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
4914299Sbbruce@ucdavis.educonstexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) {
5014299Sbbruce@ucdavis.edu    return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
5114299Sbbruce@ucdavis.edu}
5214299Sbbruce@ucdavis.edu
5314299Sbbruce@ucdavis.edutemplate <size_t N>
5414299Sbbruce@ucdavis.educonstexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); }
5514299Sbbruce@ucdavis.educonstexpr descr<0> _(char const(&)[1]) { return {}; }
5614299Sbbruce@ucdavis.edu
5712391Sjason@lowepower.comtemplate <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
5812391Sjason@lowepower.comtemplate <size_t...Digits> struct int_to_str<0, Digits...> {
5914299Sbbruce@ucdavis.edu    static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
6012391Sjason@lowepower.com};
6112391Sjason@lowepower.com
6212391Sjason@lowepower.com// Ternary description (like std::conditional)
6314299Sbbruce@ucdavis.edutemplate <bool B, size_t N1, size_t N2>
6414299Sbbruce@ucdavis.educonstexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) {
6512391Sjason@lowepower.com    return _(text1);
6612391Sjason@lowepower.com}
6714299Sbbruce@ucdavis.edutemplate <bool B, size_t N1, size_t N2>
6814299Sbbruce@ucdavis.educonstexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) {
6912391Sjason@lowepower.com    return _(text2);
7012391Sjason@lowepower.com}
7114299Sbbruce@ucdavis.edu
7214299Sbbruce@ucdavis.edutemplate <bool B, typename T1, typename T2>
7314299Sbbruce@ucdavis.educonstexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; }
7414299Sbbruce@ucdavis.edutemplate <bool B, typename T1, typename T2>
7514299Sbbruce@ucdavis.educonstexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; }
7612391Sjason@lowepower.com
7712391Sjason@lowepower.comtemplate <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) {
7812391Sjason@lowepower.com    return int_to_str<Size / 10, Size % 10>::digits;
7912391Sjason@lowepower.com}
8012391Sjason@lowepower.com
8114299Sbbruce@ucdavis.edutemplate <typename Type> constexpr descr<1, Type> _() { return {'%'}; }
8214299Sbbruce@ucdavis.edu
8314299Sbbruce@ucdavis.educonstexpr descr<0> concat() { return {}; }
8414299Sbbruce@ucdavis.edu
8514299Sbbruce@ucdavis.edutemplate <size_t N, typename... Ts>
8614299Sbbruce@ucdavis.educonstexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; }
8714299Sbbruce@ucdavis.edu
8814299Sbbruce@ucdavis.edutemplate <size_t N, typename... Ts, typename... Args>
8914299Sbbruce@ucdavis.educonstexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
9014299Sbbruce@ucdavis.edu    -> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
9114299Sbbruce@ucdavis.edu    return d + _(", ") + concat(args...);
9212391Sjason@lowepower.com}
9312391Sjason@lowepower.com
9414299Sbbruce@ucdavis.edutemplate <size_t N, typename... Ts>
9514299Sbbruce@ucdavis.educonstexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
9614299Sbbruce@ucdavis.edu    return _("{") + descr + _("}");
9712391Sjason@lowepower.com}
9812391Sjason@lowepower.com
9912391Sjason@lowepower.comNAMESPACE_END(detail)
10012391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE)
101