xref: /aosp_15_r20/external/cronet/base/export_template.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_EXPORT_TEMPLATE_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_EXPORT_TEMPLATE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker // Synopsis
9*6777b538SAndroid Build Coastguard Worker //
10*6777b538SAndroid Build Coastguard Worker // This header provides macros for using FOO_EXPORT macros with explicit
11*6777b538SAndroid Build Coastguard Worker // template instantiation declarations and definitions.
12*6777b538SAndroid Build Coastguard Worker // Generally, the FOO_EXPORT macros are used at declarations,
13*6777b538SAndroid Build Coastguard Worker // and GCC requires them to be used at explicit instantiation declarations,
14*6777b538SAndroid Build Coastguard Worker // but MSVC requires __declspec(dllexport) to be used at the explicit
15*6777b538SAndroid Build Coastguard Worker // instantiation definitions instead.
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker // Usage
18*6777b538SAndroid Build Coastguard Worker //
19*6777b538SAndroid Build Coastguard Worker // In a header file, write:
20*6777b538SAndroid Build Coastguard Worker //
21*6777b538SAndroid Build Coastguard Worker //   extern template class EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo<bar>;
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // In a source file, write:
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker //   template class EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo<bar>;
26*6777b538SAndroid Build Coastguard Worker 
27*6777b538SAndroid Build Coastguard Worker // Implementation notes
28*6777b538SAndroid Build Coastguard Worker //
29*6777b538SAndroid Build Coastguard Worker // On Windows, when building the FOO library (that is, when FOO_EXPORT expands
30*6777b538SAndroid Build Coastguard Worker // to __declspec(dllexport)), we want the two lines to expand to:
31*6777b538SAndroid Build Coastguard Worker //
32*6777b538SAndroid Build Coastguard Worker //     extern template class foo<bar>;
33*6777b538SAndroid Build Coastguard Worker //     template class FOO_EXPORT foo<bar>;
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker // In all other cases (non-Windows, and Windows when using the FOO library (that
36*6777b538SAndroid Build Coastguard Worker // is when FOO_EXPORT expands to __declspec(dllimport)), we want:
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker //     extern template class FOO_EXPORT foo<bar>;
39*6777b538SAndroid Build Coastguard Worker //     template class foo<bar>;
40*6777b538SAndroid Build Coastguard Worker //
41*6777b538SAndroid Build Coastguard Worker // The implementation of this header uses some subtle macro semantics to
42*6777b538SAndroid Build Coastguard Worker // detect what the provided FOO_EXPORT value was defined as and then
43*6777b538SAndroid Build Coastguard Worker // to dispatch to appropriate macro definitions.
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE(foo_export) \
46*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_INVOKE(DECLARE, EXPORT_TEMPLATE_STYLE(foo_export), foo_export)
47*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE(foo_export) \
48*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_INVOKE(DEFINE, EXPORT_TEMPLATE_STYLE(foo_export), foo_export)
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker // INVOKE is an internal helper macro to perform parameter replacements
51*6777b538SAndroid Build Coastguard Worker // and token pasting to chain invoke another macro.  E.g.,
52*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT)
53*6777b538SAndroid Build Coastguard Worker // will expand to call
54*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT)
55*6777b538SAndroid Build Coastguard Worker // (but with FOO_EXPORT expanded too).
56*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_INVOKE(which, style, foo_export) \
57*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_INVOKE_2(which, style, foo_export)
58*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_INVOKE_2(which, style, foo_export) \
59*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_##which##_##style(foo_export)
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker // Default style is to apply the FOO_EXPORT macro at declaration sites.
62*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE_DEFAULT(foo_export) foo_export
63*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE_DEFAULT(foo_export)
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker // The "declspec" style is used when FOO_EXPORT is defined
66*6777b538SAndroid Build Coastguard Worker // as __declspec(dllexport), which MSVC requires to be used at
67*6777b538SAndroid Build Coastguard Worker // definition sites instead.
68*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DECLARE_EXPORT_DLLEXPORT(foo_export)
69*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_DEFINE_EXPORT_DLLEXPORT(foo_export) foo_export
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies which
72*6777b538SAndroid Build Coastguard Worker // export style needs to be used for the provided FOO_EXPORT macro definition.
73*6777b538SAndroid Build Coastguard Worker // "", "__attribute__(...)", and "__declspec(dllimport)" are mapped
74*6777b538SAndroid Build Coastguard Worker // to "DEFAULT"; while "__declspec(dllexport)" is mapped to "EXPORT_DLLEXPORT".
75*6777b538SAndroid Build Coastguard Worker // (NaCl headers define "DLLEXPORT" already, else we'd use that.
76*6777b538SAndroid Build Coastguard Worker // TODO(thakis): Rename once nacl is gone.)
77*6777b538SAndroid Build Coastguard Worker //
78*6777b538SAndroid Build Coastguard Worker // It's implemented with token pasting to transform the __attribute__ and
79*6777b538SAndroid Build Coastguard Worker // __declspec annotations into macro invocations.  E.g., if FOO_EXPORT is
80*6777b538SAndroid Build Coastguard Worker // defined as "__declspec(dllimport)", it undergoes the following sequence of
81*6777b538SAndroid Build Coastguard Worker // macro substitutions:
82*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_STYLE(FOO_EXPORT)
83*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport))
84*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)
85*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
86*6777b538SAndroid Build Coastguard Worker //     DEFAULT
87*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE(foo_export) EXPORT_TEMPLATE_STYLE_2(foo_export)
88*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_2(foo_export) \
89*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##foo_export
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker // Internal helper macros for EXPORT_TEMPLATE_STYLE.
92*6777b538SAndroid Build Coastguard Worker //
93*6777b538SAndroid Build Coastguard Worker // XXX: C++ reserves all identifiers containing "__" for the implementation,
94*6777b538SAndroid Build Coastguard Worker // but "__attribute__" and "__declspec" already contain "__" and the token-paste
95*6777b538SAndroid Build Coastguard Worker // operator can only add characters; not remove them.  To minimize the risk of
96*6777b538SAndroid Build Coastguard Worker // conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random
97*6777b538SAndroid Build Coastguard Worker // 128-bit string, encoded in Base64) in the macro name.
98*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT
99*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \
100*6777b538SAndroid Build Coastguard Worker   DEFAULT
101*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \
102*6777b538SAndroid Build Coastguard Worker   EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker // Internal helper macros for EXPORT_TEMPLATE_STYLE.
105*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport EXPORT_DLLEXPORT
106*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker // Sanity checks.
109*6777b538SAndroid Build Coastguard Worker //
110*6777b538SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as
111*6777b538SAndroid Build Coastguard Worker // EXPORT_TEMPLATE_DECLARE and EXPORT_TEMPLATE_DEFINE do to check that they're
112*6777b538SAndroid Build Coastguard Worker // working correctly.  When they're working correctly, the sequence of macro
113*6777b538SAndroid Build Coastguard Worker // replacements should go something like:
114*6777b538SAndroid Build Coastguard Worker //
115*6777b538SAndroid Build Coastguard Worker //     EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
116*6777b538SAndroid Build Coastguard Worker //
117*6777b538SAndroid Build Coastguard Worker //     static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
118*6777b538SAndroid Build Coastguard Worker //         EXPORT_TEMPLATE_STYLE(__declspec(dllimport)),
119*6777b538SAndroid Build Coastguard Worker //         __declspec(dllimport)), "__declspec(dllimport)");
120*6777b538SAndroid Build Coastguard Worker //
121*6777b538SAndroid Build Coastguard Worker //     static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
122*6777b538SAndroid Build Coastguard Worker //         DEFAULT, __declspec(dllimport)), "__declspec(dllimport)");
123*6777b538SAndroid Build Coastguard Worker //
124*6777b538SAndroid Build Coastguard Worker //     static_assert(EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(
125*6777b538SAndroid Build Coastguard Worker //         __declspec(dllimport)), "__declspec(dllimport)");
126*6777b538SAndroid Build Coastguard Worker //
127*6777b538SAndroid Build Coastguard Worker //     static_assert(true, "__declspec(dllimport)");
128*6777b538SAndroid Build Coastguard Worker //
129*6777b538SAndroid Build Coastguard Worker // When they're not working correctly, a syntax error should occur instead.
130*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST(want, foo_export)                               \
131*6777b538SAndroid Build Coastguard Worker   static_assert(                                                             \
132*6777b538SAndroid Build Coastguard Worker       EXPORT_TEMPLATE_INVOKE(TEST_##want, EXPORT_TEMPLATE_STYLE(foo_export), \
133*6777b538SAndroid Build Coastguard Worker                              foo_export),                                    \
134*6777b538SAndroid Build Coastguard Worker       #foo_export)
135*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true
136*6777b538SAndroid Build Coastguard Worker #define EXPORT_TEMPLATE_TEST_EXPORT_DLLEXPORT_EXPORT_DLLEXPORT(...) true
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, );
139*6777b538SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
140*6777b538SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(EXPORT_DLLEXPORT, __declspec(dllexport));
141*6777b538SAndroid Build Coastguard Worker EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST
144*6777b538SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT
145*6777b538SAndroid Build Coastguard Worker #undef EXPORT_TEMPLATE_TEST_EXPORT_DLLEXPORT_EXPORT_DLLEXPORT
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker #endif  // BASE_EXPORT_TEMPLATE_H_
148