MeshLib C Docs
Loading...
Searching...
No Matches
__mrbind_c_details.h
Go to the documentation of this file.
1#pragma once
2
3#include <MRCMisc/common.h>
4#include <MRCMisc/exports.h>
5
6#include <stdexcept>
7#include <utility>
8
9// Are we compiling with exceptions enabled?
10#ifndef MRC_ENABLE_EXCEPTIONS
11# ifdef __cpp_exceptions
12# define MRC_ENABLE_EXCEPTIONS 1
13# else
14# define MRC_ENABLE_EXCEPTIONS 0
15# endif
16#endif
17
19{
20 #if MRC_ENABLE_EXCEPTIONS
21 #define MRBINDC_THROW(message_, .../*result_cpp_type_*/) throw std::runtime_error(+(message_))
22 #else
23 [[noreturn]] MRC_API void ThrowWithExceptionsDisabled(const char *message);
24 #define MRBINDC_THROW(message_, .../*result_cpp_type_*/) (mrbindc_details::ThrowWithExceptionsDisabled(message_), ((__VA_ARGS__ (*)())0)())
25 #endif
26
27 // Those are used to handle by-value arguments of class types, which are passed as a pointer plus a enum explaining how to handle it.
28 // The `cpp_type_without_wrapper_` vs `cpp_type_` are different for optionals: `cpp_type_` is either `T` or `std::optional<T>`, while `cpp_type_without_wrapper_` is always the `T` itself.
29 #define MRBINDC_CLASSARG_DEF_CTOR(param_, .../*cpp_type_*/) param_##_pass_by == MR_PassBy_DefaultConstruct ? (param_ ? MRBINDC_THROW("Expected a null pointer to be passed to `" #param_ " because `MR_PassBy_DefaultConstruct` was used.", __VA_ARGS__) : __VA_ARGS__{}) :
30 #define MRBINDC_CLASSARG_COPY(param_, cpp_type_without_wrapper_, .../*cpp_type_*/) param_##_pass_by == MR_PassBy_Copy ? __VA_ARGS__(*(MRBINDC_IDENTITY cpp_type_without_wrapper_ *)param_) :
31 #define MRBINDC_CLASSARG_MOVE(param_, cpp_type_without_wrapper_, .../*cpp_type_*/) param_##_pass_by == MR_PassBy_Move ? __VA_ARGS__(std::move(*(MRBINDC_IDENTITY cpp_type_without_wrapper_ *)param_)) :
32 #define MRBINDC_CLASSARG_DEF_ARG(param_, enum_constant_, default_arg_, .../*cpp_type_*/) param_##_pass_by == enum_constant_ ? (param_ ? MRBINDC_THROW("Expected a null pointer to be passed to `" #param_ " because `" #enum_constant_ "` was used.", __VA_ARGS__) : __VA_ARGS__(default_arg_)) :
33 #define MRBINDC_CLASSARG_NO_DEF_ARG(param_, enum_constant_, .../*cpp_type_*/) param_##_pass_by == enum_constant_ ? MRBINDC_THROW("Function parameter `" #param_ " doesn't support `" #enum_constant_ "`.", __VA_ARGS__) :
34 #define MRBINDC_CLASSARG_END(param_, .../*cpp_type_*/) true ? MRBINDC_THROW("Invalid `MR_PassBy` enum value specified for function parameter `" #param_ ".", __VA_ARGS__) : ((__VA_ARGS__ (*)())0)() // We need the dumb fallback to keep the overall type equal to `cpptype_` instead of `void`, which messes things up.
35
36 // This is used by the `MRBINDC_CLASSARG_GUARD()` macro, see below.
37 template <typename T>
39 {
40 T *ptr = nullptr;
41 ClassArgGuard(T *new_ptr, MR_PassBy &pass_by)
42 {
43 if (pass_by != MR_PassBy_MoveAndDestroy)
44 return;
45 ptr = new_ptr;
46 pass_by = MR_PassBy_Move;
47 }
48 ClassArgGuard(const ClassArgGuard &) = delete;
51 {
52 if (ptr)
53 delete ptr;
54 }
55 };
56
57 // This is used to handle `MR_PassBy_MoveAndDestroy`.
58 #define MRBINDC_CLASSARG_GUARD(param_, .../*cpp_type_without_wrapper_*/) mrbindc_details::ClassArgGuard<__VA_ARGS__> _classarg_guard_##param_((__VA_ARGS__ *)param_, param_##_pass_by)
59
60 // Converts an rvalue to an lvalue.
61 template <typename T> constexpr T &unmove(T &&value) {return static_cast<T &>(value);}
62} // namespace mrbindc_details
63
64
65#define MRBINDC_IDENTITY(...) __VA_ARGS__
66
67#if defined(_MSC_VER) && !defined(__clang__)
68#define MRBINDC_IGNORE_DEPRECATION(...) _Pragma("warning(push)") _Pragma("warning(disable: 4996)") __VA_ARGS__ _Pragma("warning(pop)")
69#else
70#define MRBINDC_IGNORE_DEPRECATION(...) _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") __VA_ARGS__ _Pragma("GCC diagnostic pop")
71#endif
72
73
74// Define `MRBINDC_BIT_CAST()`. We have several implementations to choose from.
75// [
76
77// std::bit_cast
78#ifndef MRBINDC_BIT_CAST
79#if __has_include(<version>)
80#include <version>
81#ifdef __cpp_lib_bit_cast
82#include <bit>
83#define MRBINDC_BIT_CAST(p_type_, ...) std::bit_cast<MRBINDC_IDENTITY p_type_>(__VA_ARGS__)
84#endif
85#endif
86#endif
87
88// __builtin_bit_cast
89#ifndef MRBINDC_BIT_CAST
90#ifdef __has_builtin
91#if __has_builtin(__builtin_bit_cast)
92#define MRBINDC_BIT_CAST(p_type_, ...) __builtin_bit_cast(MRBINDC_IDENTITY p_type_, __VA_ARGS__) // How this handles commas in the first argument is a mystery, but it does.
93#endif
94#endif
95#endif
96
97// reinterpret_cast
98#ifndef MRBINDC_BIT_CAST
99#include <type_traits>
100#define MRBINDC_BIT_CAST(p_type_, ...) (MRBINDC_IDENTITY p_type_ (reinterpret_cast<std::add_lvalue_reference_t<std::add_const_t<MRBINDC_IDENTITY p_type_>>>(mrbindc_details::unmove(__VA_ARGS__))))
101#endif
102
103// ]
104
MR_PassBy
Definition common.h:13
@ MR_PassBy_MoveAndDestroy
Definition common.h:17
@ MR_PassBy_Move
Definition common.h:16
#define MRC_API
Definition include/MRCMisc/exports.h:11
Definition __mrbind_c_details.h:19
constexpr T & unmove(T &&value)
Definition __mrbind_c_details.h:61
MRC_API void ThrowWithExceptionsDisabled(const char *message)
ClassArgGuard(const ClassArgGuard &)=delete
T * ptr
Definition __mrbind_c_details.h:40
~ClassArgGuard()
Definition __mrbind_c_details.h:50
ClassArgGuard & operator=(const ClassArgGuard &)=delete
ClassArgGuard(T *new_ptr, MR_PassBy &pass_by)
Definition __mrbind_c_details.h:41