1  
//
1  
//
2  
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/cppalliance/capy
7  
// Official repository: https://github.com/cppalliance/capy
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_CAPY_DETAIL_TYPE_ID_HPP
10  
#ifndef BOOST_CAPY_DETAIL_TYPE_ID_HPP
11  
#define BOOST_CAPY_DETAIL_TYPE_ID_HPP
11  
#define BOOST_CAPY_DETAIL_TYPE_ID_HPP
12  

12  

13  
#include <boost/capy/detail/config.hpp>
13  
#include <boost/capy/detail/config.hpp>
14  

14  

15  
#if BOOST_CAPY_NO_RTTI
15  
#if BOOST_CAPY_NO_RTTI
16  

16  

17  
//------------------------------------------------
17  
//------------------------------------------------
18  
// Custom implementation (no RTTI)
18  
// Custom implementation (no RTTI)
19  
//------------------------------------------------
19  
//------------------------------------------------
20  

20  

21  
#include <compare>
21  
#include <compare>
22  
#include <cstddef>
22  
#include <cstddef>
23  
#include <cstdint>
23  
#include <cstdint>
24  
#include <string_view>
24  
#include <string_view>
25  
#include <type_traits>
25  
#include <type_traits>
26  

26  

27  
namespace boost {
27  
namespace boost {
28  
namespace capy {
28  
namespace capy {
29  
namespace detail {
29  
namespace detail {
30  

30  

31  
template<typename T>
31  
template<typename T>
32  
constexpr std::string_view
32  
constexpr std::string_view
33  
type_name_impl() noexcept
33  
type_name_impl() noexcept
34  
{
34  
{
35  
    constexpr auto strlen_ce = [](char const* s) constexpr noexcept {
35  
    constexpr auto strlen_ce = [](char const* s) constexpr noexcept {
36  
        std::size_t n = 0;
36  
        std::size_t n = 0;
37  
        while(s[n] != '\0')
37  
        while(s[n] != '\0')
38  
            ++n;
38  
            ++n;
39  
        return n;
39  
        return n;
40  
    };
40  
    };
41  

41  

42  
    constexpr auto find = [](char const* s, std::size_t len, char c) constexpr noexcept {
42  
    constexpr auto find = [](char const* s, std::size_t len, char c) constexpr noexcept {
43  
        for(std::size_t i = 0; i < len; ++i)
43  
        for(std::size_t i = 0; i < len; ++i)
44  
            if(s[i] == c)
44  
            if(s[i] == c)
45  
                return i;
45  
                return i;
46  
        return len;
46  
        return len;
47  
    };
47  
    };
48  

48  

49  
    constexpr auto rfind = [](char const* s, std::size_t len, char c) constexpr noexcept {
49  
    constexpr auto rfind = [](char const* s, std::size_t len, char c) constexpr noexcept {
50  
        for(std::size_t i = len; i > 0; --i)
50  
        for(std::size_t i = len; i > 0; --i)
51  
            if(s[i - 1] == c)
51  
            if(s[i - 1] == c)
52  
                return i - 1;
52  
                return i - 1;
53  
        return len;
53  
        return len;
54  
    };
54  
    };
55  

55  

56  
#if defined(__clang__)
56  
#if defined(__clang__)
57  
    constexpr char const* s = __PRETTY_FUNCTION__;
57  
    constexpr char const* s = __PRETTY_FUNCTION__;
58  
    constexpr std::size_t len = strlen_ce(s);
58  
    constexpr std::size_t len = strlen_ce(s);
59  
    constexpr std::size_t start = find(s, len, '=') + 2;
59  
    constexpr std::size_t start = find(s, len, '=') + 2;
60  
    constexpr std::size_t end = rfind(s, len, ']');
60  
    constexpr std::size_t end = rfind(s, len, ']');
61  
    return {s + start, end - start};
61  
    return {s + start, end - start};
62  

62  

63  
#elif defined(__GNUC__)
63  
#elif defined(__GNUC__)
64  
    constexpr char const* s = __PRETTY_FUNCTION__;
64  
    constexpr char const* s = __PRETTY_FUNCTION__;
65  
    constexpr std::size_t len = strlen_ce(s);
65  
    constexpr std::size_t len = strlen_ce(s);
66  
    constexpr std::size_t start = find(s, len, '=') + 2;
66  
    constexpr std::size_t start = find(s, len, '=') + 2;
67  
    constexpr std::size_t end = rfind(s, len, ']');
67  
    constexpr std::size_t end = rfind(s, len, ']');
68  
    return {s + start, end - start};
68  
    return {s + start, end - start};
69  

69  

70  
#elif defined(_MSC_VER)
70  
#elif defined(_MSC_VER)
71  
    constexpr char const* s = __FUNCSIG__;
71  
    constexpr char const* s = __FUNCSIG__;
72  
    constexpr std::size_t len = strlen_ce(s);
72  
    constexpr std::size_t len = strlen_ce(s);
73  
    constexpr std::size_t start = find(s, len, '<') + 1;
73  
    constexpr std::size_t start = find(s, len, '<') + 1;
74  
    constexpr std::size_t end = rfind(s, len, '>');
74  
    constexpr std::size_t end = rfind(s, len, '>');
75  
    return {s + start, end - start};
75  
    return {s + start, end - start};
76  

76  

77  
#else
77  
#else
78  
    return "unknown";
78  
    return "unknown";
79  
#endif
79  
#endif
80  
}
80  
}
81  

81  

82  
template<typename T>
82  
template<typename T>
83  
inline constexpr std::string_view type_name = type_name_impl<T>();
83  
inline constexpr std::string_view type_name = type_name_impl<T>();
84  

84  

85  
class type_info
85  
class type_info
86  
{
86  
{
87  
    void const* id_;
87  
    void const* id_;
88  
    std::string_view name_;
88  
    std::string_view name_;
89  

89  

90  
    constexpr explicit
90  
    constexpr explicit
91  
    type_info(void const* id, std::string_view name) noexcept
91  
    type_info(void const* id, std::string_view name) noexcept
92  
        : id_(id)
92  
        : id_(id)
93  
        , name_(name)
93  
        , name_(name)
94  
    {
94  
    {
95  
    }
95  
    }
96  

96  

97  
    template<typename T>
97  
    template<typename T>
98  
    friend struct type_id_impl;
98  
    friend struct type_id_impl;
99  

99  

100  
public:
100  
public:
101  
    type_info(type_info const&) = default;
101  
    type_info(type_info const&) = default;
102  
    type_info& operator=(type_info const&) = default;
102  
    type_info& operator=(type_info const&) = default;
103  

103  

104  
    constexpr std::string_view
104  
    constexpr std::string_view
105  
    name() const noexcept
105  
    name() const noexcept
106  
    {
106  
    {
107  
        return name_;
107  
        return name_;
108  
    }
108  
    }
109  

109  

110  
    constexpr bool
110  
    constexpr bool
111  
    operator==(type_info const& rhs) const noexcept
111  
    operator==(type_info const& rhs) const noexcept
112  
    {
112  
    {
113  
        return id_ == rhs.id_;
113  
        return id_ == rhs.id_;
114  
    }
114  
    }
115  

115  

116  
    constexpr bool
116  
    constexpr bool
117  
    operator!=(type_info const& rhs) const noexcept
117  
    operator!=(type_info const& rhs) const noexcept
118  
    {
118  
    {
119  
        return id_ != rhs.id_;
119  
        return id_ != rhs.id_;
120  
    }
120  
    }
121  

121  

122  
    constexpr bool
122  
    constexpr bool
123  
    before(type_info const& rhs) const noexcept
123  
    before(type_info const& rhs) const noexcept
124  
    {
124  
    {
125  
        return id_ < rhs.id_;
125  
        return id_ < rhs.id_;
126  
    }
126  
    }
127  

127  

128  
    std::uintptr_t
128  
    std::uintptr_t
129  
    hash_code() const noexcept
129  
    hash_code() const noexcept
130  
    {
130  
    {
131  
        return reinterpret_cast<std::uintptr_t>(id_);
131  
        return reinterpret_cast<std::uintptr_t>(id_);
132  
    }
132  
    }
133  
};
133  
};
134  

134  

135  
template<typename T>
135  
template<typename T>
136  
struct type_id_impl
136  
struct type_id_impl
137  
{
137  
{
138  
    inline static constexpr char tag{};
138  
    inline static constexpr char tag{};
139  
    inline static constexpr type_info value{&tag, type_name<T>};
139  
    inline static constexpr type_info value{&tag, type_name<T>};
140  
};
140  
};
141  

141  

142  
/// Returns type_info for type T (ignores top-level cv-qualifiers)
142  
/// Returns type_info for type T (ignores top-level cv-qualifiers)
143  
template<typename T>
143  
template<typename T>
144  
inline constexpr type_info const&
144  
inline constexpr type_info const&
145  
type_id() noexcept
145  
type_id() noexcept
146  
{
146  
{
147  
    return type_id_impl<std::remove_cv_t<T>>::value;
147  
    return type_id_impl<std::remove_cv_t<T>>::value;
148  
}
148  
}
149  

149  

150  
class type_index
150  
class type_index
151  
{
151  
{
152  
    type_info const* info_;
152  
    type_info const* info_;
153  

153  

154  
public:
154  
public:
155  
    constexpr
155  
    constexpr
156  
    type_index(type_info const& info) noexcept
156  
    type_index(type_info const& info) noexcept
157  
        : info_(&info)
157  
        : info_(&info)
158  
    {
158  
    {
159  
    }
159  
    }
160  

160  

161  
    constexpr std::string_view
161  
    constexpr std::string_view
162  
    name() const noexcept
162  
    name() const noexcept
163  
    {
163  
    {
164  
        return info_->name();
164  
        return info_->name();
165  
    }
165  
    }
166  

166  

167  
    std::uintptr_t
167  
    std::uintptr_t
168  
    hash_code() const noexcept
168  
    hash_code() const noexcept
169  
    {
169  
    {
170  
        return reinterpret_cast<std::uintptr_t>(info_);
170  
        return reinterpret_cast<std::uintptr_t>(info_);
171  
    }
171  
    }
172  

172  

173  
    constexpr bool
173  
    constexpr bool
174  
    operator==(type_index const& rhs) const noexcept = default;
174  
    operator==(type_index const& rhs) const noexcept = default;
175  

175  

176  
    constexpr std::strong_ordering
176  
    constexpr std::strong_ordering
177  
    operator<=>(type_index const& rhs) const noexcept = default;
177  
    operator<=>(type_index const& rhs) const noexcept = default;
178  
};
178  
};
179  

179  

180  
} // detail
180  
} // detail
181  
} // capy
181  
} // capy
182  
} // boost
182  
} // boost
183  

183  

184  
template<>
184  
template<>
185  
struct std::hash<boost::capy::detail::type_index>
185  
struct std::hash<boost::capy::detail::type_index>
186  
{
186  
{
187  
    std::size_t
187  
    std::size_t
188  
    operator()(boost::capy::detail::type_index const& ti) const noexcept
188  
    operator()(boost::capy::detail::type_index const& ti) const noexcept
189  
    {
189  
    {
190  
        return ti.hash_code();
190  
        return ti.hash_code();
191  
    }
191  
    }
192  
};
192  
};
193  

193  

194  
#else // BOOST_CAPY_NO_RTTI
194  
#else // BOOST_CAPY_NO_RTTI
195  

195  

196  
//------------------------------------------------
196  
//------------------------------------------------
197  
// Standard RTTI implementation
197  
// Standard RTTI implementation
198  
//------------------------------------------------
198  
//------------------------------------------------
199  

199  

200  
#include <typeinfo>
200  
#include <typeinfo>
201  
#include <typeindex>
201  
#include <typeindex>
202  

202  

203  
namespace boost {
203  
namespace boost {
204  
namespace capy {
204  
namespace capy {
205  
namespace detail {
205  
namespace detail {
206  

206  

207  
using type_info = std::type_info;
207  
using type_info = std::type_info;
208  
using type_index = std::type_index;
208  
using type_index = std::type_index;
209  

209  

210  
/// Returns type_info for type T
210  
/// Returns type_info for type T
211  
template<typename T>
211  
template<typename T>
212  
inline constexpr type_info const&
212  
inline constexpr type_info const&
213  
type_id() noexcept
213  
type_id() noexcept
214  
{
214  
{
215  
    return typeid(T);
215  
    return typeid(T);
216  
}
216  
}
217  

217  

218  
} // detail
218  
} // detail
219  
} // capy
219  
} // capy
220  
} // boost
220  
} // boost
221  

221  

222  
#endif // BOOST_CAPY_NO_RTTI
222  
#endif // BOOST_CAPY_NO_RTTI
223  

223  

224  
#endif
224  
#endif