MeshLib C++ Docs
Loading...
Searching...
No Matches
MRMacros.h
Go to the documentation of this file.
1#pragma once
2
3// Those are generic helper macros that don't have their own headers.
4
5// Convert to a string.
6#define MR_STR(...) MR_STR_(__VA_ARGS__)
7#define MR_STR_(...) #__VA_ARGS__
8
9// Returns the argument unchanged.
10#define MR_IDENTITY(...) __VA_ARGS__
11
12// A helper for writing preprocessor loops.
13#define MR_END(...) DETAIL_MR_END(__VA_ARGS__)
14#define DETAIL_MR_END(...) __VA_ARGS__##_END
15
16// Concat strings
17#define MR_CONCAT( a, b ) MR_CONCAT_( a, b )
18#define MR_CONCAT_( a, b ) a##b
19
20#define MR_CONCAT3( a, b, c ) MR_CONCAT3_( a, b, c )
21#define MR_CONCAT3_( a, b, c ) a##b##c
22
23// If the compiler supports `requires`, expands to `requires(...)`. Otherwise to nothing.
24// This is primarily useful for code that must be usable in Cuda, since everywhere else we're free to use C++20 and newer.
25// While Clang 14 technically supports `requires`, we're getting a few weird issues with it (make a nested aggregate class,
26// in the enclosing class make a `MR::Vector` of it, observe that `std::default_initializable` gets baked as `false` on it,
27// disabling some member functions such as `.resize()`).
28#if __cpp_concepts && __has_include(<concepts>) && !(defined(__clang__) && __clang_major__ <= 14) && !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 12)
29# define MR_HAS_REQUIRES 1
30# define MR_REQUIRES_IF_SUPPORTED(...) requires(__VA_ARGS__)
31# define MR_SAME_TYPE_TEMPLATE_PARAM(target_, name_) std::same_as<target_> name_ = target_
32#else
33# define MR_HAS_REQUIRES 0
34# define MR_REQUIRES_IF_SUPPORTED(...)
35# define MR_SAME_TYPE_TEMPLATE_PARAM(target_, name_) typename name_ = target_
36#endif
37
38
39#ifdef _MSC_VER
40#define MR_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] // The unprefixed version has no effect on MSVC.
41#else
42#define MR_NO_UNIQUE_ADDRESS [[no_unique_address]]
43#endif
44
45
46// Are we using the old buggy MSVC preprocessor?
47#if defined(_MSC_VER) && !defined(__clang__) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL == 1)
48#define MR_LEGACY_MSVC_PREPROCESSOR 1
49#else
50#define MR_LEGACY_MSVC_PREPROCESSOR 0
51#endif
52
53// `MR_TRIM_LEADING_COMMA(,a,b,c)` returns `a,b,c`.
54#if MR_LEGACY_MSVC_PREPROCESSOR
55#define MR_TRIM_LEADING_COMMA(...) DETAIL_MR_TRIM_LEADING_COMMA_ DETAIL_MR_TRIM_LEADING_COMMA_DEFER(__VA_ARGS__)
56#define DETAIL_MR_TRIM_LEADING_COMMA_DEFER
57#else
58#define MR_TRIM_LEADING_COMMA(...) DETAIL_MR_TRIM_LEADING_COMMA_(__VA_ARGS__)
59#endif
60#define DETAIL_MR_TRIM_LEADING_COMMA_(x, ...) DETAIL_MR_TRIM_LEADING_COMMA_EMPTY(x) __VA_ARGS__
61#define DETAIL_MR_TRIM_LEADING_COMMA_EMPTY()