/* pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time Copyright (c) 2016 Wenzel Jakob 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" PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) #if !defined(_MSC_VER) # define PYBIND11_DESCR_CONSTEXPR static constexpr #else # define PYBIND11_DESCR_CONSTEXPR const #endif /* Concatenate type signatures at compile time */ template struct descr { char text[N + 1]{'\0'}; constexpr descr() = default; // NOLINTNEXTLINE(google-explicit-constructor) constexpr descr(char const (&s)[N + 1]) : descr(s, make_index_sequence()) {} template constexpr descr(char const (&s)[N + 1], index_sequence) : text{s[Is]..., '\0'} {} template // NOLINTNEXTLINE(google-explicit-constructor) constexpr descr(char c, Chars... cs) : text{c, static_cast(cs)..., '\0'} {} static constexpr std::array types() { return {{&typeid(Ts)..., nullptr}}; } }; template constexpr descr plus_impl(const descr &a, const descr &b, index_sequence, index_sequence) { PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b); return {a.text[Is1]..., b.text[Is2]...}; } template constexpr descr operator+(const descr &a, const descr &b) { return plus_impl(a, b, make_index_sequence(), make_index_sequence()); } template constexpr descr const_name(char const (&text)[N]) { return descr(text); } constexpr descr<0> const_name(char const (&)[1]) { return {}; } template struct int_to_str : int_to_str {}; template struct int_to_str<0, Digits...> { // WARNING: This only works with C++17 or higher. static constexpr auto digits = descr(('0' + Digits)...); }; // Ternary description (like std::conditional) template constexpr enable_if_t> const_name(char const (&text1)[N1], char const (&)[N2]) { return const_name(text1); } template constexpr enable_if_t> const_name(char const (&)[N1], char const (&text2)[N2]) { return const_name(text2); } template constexpr enable_if_t const_name(const T1 &d, const T2 &) { return d; } template constexpr enable_if_t const_name(const T1 &, const T2 &d) { return d; } template auto constexpr const_name() -> remove_cv_t::digits)> { return int_to_str::digits; } template constexpr descr<1, Type> const_name() { return {'%'}; } // If "_" is defined as a macro, py::detail::_ cannot be provided. // It is therefore best to use py::detail::const_name universally. // This block is for backward compatibility only. // (The const_name code is repeated to avoid introducing a "_" #define ourselves.) #ifndef _ # define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY template constexpr descr _(char const (&text)[N]) { return const_name(text); } template constexpr enable_if_t> _(char const (&text1)[N1], char const (&text2)[N2]) { return const_name(text1, text2); } template constexpr enable_if_t> _(char const (&text1)[N1], char const (&text2)[N2]) { return const_name(text1, text2); } template constexpr enable_if_t _(const T1 &d1, const T2 &d2) { return const_name(d1, d2); } template constexpr enable_if_t _(const T1 &d1, const T2 &d2) { return const_name(d1, d2); } template auto constexpr _() -> remove_cv_t::digits)> { return const_name(); } template constexpr descr<1, Type> _() { return const_name(); } #endif // #ifndef _ constexpr descr<0> concat() { return {}; } template constexpr descr concat(const descr &descr) { return descr; } #ifdef __cpp_fold_expressions template constexpr descr operator,(const descr &a, const descr &b) { return a + const_name(", ") + b; } template constexpr auto concat(const descr &d, const Args &...args) { return (d, ..., args); } #else template constexpr auto concat(const descr &d, const Args &...args) -> decltype(std::declval>() + concat(args...)) { return d + const_name(", ") + concat(args...); } #endif template constexpr descr type_descr(const descr &descr) { return const_name("{") + descr + const_name("}"); } PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)