Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/metaprogramming/enableIf.hpp
40930 views
1
/*
2
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#ifndef SHARE_METAPROGRAMMING_ENABLEIF_HPP
26
#define SHARE_METAPROGRAMMING_ENABLEIF_HPP
27
28
#include "metaprogramming/logical.hpp"
29
#include <type_traits>
30
31
// Retained temporarily for backward compatibility.
32
// For function template SFINAE, use the ENABLE_IF macro below.
33
// For class template SFINAE, use std::enable_if_t directly.
34
template<bool cond, typename T = void>
35
using EnableIf = std::enable_if<cond, T>;
36
37
// ENABLE_IF(Condition...)
38
// ENABLE_IF_SDEFN(Condition...)
39
//
40
// The ENABLE_IF macro can be used in a function template parameter list to
41
// control the presence of that overload via SFINAE.
42
//
43
// When the declaration and definition of a function template are separate,
44
// only the declaration can use ENABLE_IF in the template parameter list.
45
// The definition should instead use ENABLE_IF_SDEFN with an _equivalent_
46
// (C++14 14.4 and 14.5.6.1) Condition for the corresponding template
47
// parameter. ("SDEFN" is short for "SEPARATE_DEFINITION".)
48
//
49
// Condition must be a constant expression whose value is convertible to
50
// bool. The Condition is captured as a variadic macro parameter so that it
51
// may contain unparenthesized commas.
52
//
53
// An example of the usage of the ENABLE_IF macro is
54
//
55
// template<typename T,
56
// ENABLE_IF(std::is_integral<T>::value),
57
// ENABLE_IF(std::is_signed<T>::value)>
58
// void foo(T x) { ... }
59
//
60
// That definition will not be considered in a call to foo unless T is a
61
// signed integral type.
62
//
63
// An alternative to two ENABLE_IF parameters would be single parameter
64
// that is a conjunction of the expressions. The benefit of multiple
65
// ENABLE_IF parameters is the compiler may provide more information in
66
// certain error contexts.
67
//
68
// Details:
69
//
70
// With C++98/03 there are 2 ways to use enable_if with function templates:
71
//
72
// (1) As the return type
73
// (2) As an extra parameter
74
//
75
// C++11 adds another way, using an extra anonymous non-type template
76
// parameter with a default value, i.e.
77
//
78
// std::enable_if_t<CONDITION, int> = 0
79
//
80
// (The left-hand side is the 'int' type of the anonymous parameter. The
81
// right-hand side is the default value. The use of 'int' and '0' are
82
// conventional; the specific type and value don't matter, so long as they
83
// are compatible.)
84
//
85
// Compared to (1) this has the benefit of less cluttered syntax for the
86
// function signature. Compared to (2) it avoids polluting the signature
87
// with dummy extra parameters. And there are cases where this new approach
88
// can be used while neither of the others is even possible.
89
//
90
// Using an extra template parameter is somewhat syntactically complex, with
91
// a number of details to get right. However, that complexity can be
92
// largely hidden using a macro, resulting in more readable uses of SFINAE
93
// for function templates.
94
//
95
// One of those details is that a function template definition that is
96
// separate from its declaration cannot have a default value. Thus,
97
// ENABLE_IF can't be used in such a definition. But the type expression in
98
// the separate definition must be equivalent (C++14 14.4 and 14.5.6.1) to
99
// that in the declation. The ENABLE_IF_SDEFN macro provides the common
100
// code for the separate definition that must match the corresponding
101
// declaration code at the token level.
102
//
103
// The Condition must be wrapped in parenthesis in the expansion. Otherwise,
104
// a '>' operator in the expression may be misinterpreted as the end of the
105
// template parameter list. But rather than simply wrapping in parenthesis,
106
// Condition is wrapped in an explicit conversion to bool, so the value need
107
// not be *implicitly* convertible.
108
//
109
// There is a problem when Condition is not dependent on any template
110
// parameter. Such a Condition will be evaluated at template definition
111
// time, as part of template type checking. If Condition is false, that
112
// will result in a compile-time error rather than the desired SFINAE
113
// exclusion. This situation is sufficiently rare that no additional
114
// macro support is provided for it. (One solution is to add a new
115
// type parameter defaulted to the type being checked in Condition, and
116
// use that new parameter instead in Condition. There is an automatic
117
// macro-based solution, but it involves the __COUNTER__ extension.)
118
//
119
// Some references suggest a different approach to using a template
120
// parameter for SFINAE. An anonymous type parameter with a default type
121
// that uses std::enable_if can also be used in some cases, i.e.
122
//
123
// typename = std::enable_if_t<CONDITION>
124
//
125
// However, this doesn't work when there are overloads that need to be
126
// selected amongst via SFINAE. Two signatures that differ only in a
127
// template parameter default are not distinct overloads, they are multiple
128
// definitions of the same function.
129
//
130
// Some versions of gcc permit ENABLE_IF to be used in some separate
131
// definitions. Other toolchains reject such usage.
132
//
133
// The expansion of ENABLE_IF doesn't use ENABLE_IF_SDEFN (or both use a
134
// common helper) because of issues with the Visual Studio preprocessor's
135
// handling of variadic macros.
136
137
#define ENABLE_IF(...) \
138
std::enable_if_t<bool(__VA_ARGS__), int> = 0
139
140
#define ENABLE_IF_SDEFN(...) \
141
std::enable_if_t<bool(__VA_ARGS__), int>
142
143
#endif // SHARE_METAPROGRAMMING_ENABLEIF_HPP
144
145