Modified: trunk/Source/WTF/ChangeLog (230108 => 230109)
--- trunk/Source/WTF/ChangeLog 2018-03-30 17:30:18 UTC (rev 230108)
+++ trunk/Source/WTF/ChangeLog 2018-03-30 17:36:20 UTC (rev 230109)
@@ -1,3 +1,25 @@
+2018-03-30 JF Bastien <[email protected]>
+
+ Introduce WTF_LAZY_INSTANTIATE
+ https://bugs.webkit.org/show_bug.cgi?id=184169
+ <rdar://problem/39023385>
+
+ Reviewed by Mark Lam.
+
+ As part of #184164 I'm adding some forwarding methods to
+ WTF::String. These need to forward RetainPtr and CString, and
+ usually that would require #include'ing RetainPtr.h and CString.h
+ to WTFString.h which isn't really something we should do.
+
+ Introduce WTF_LAZY_INSTANTIATE to forward-declare functions which
+ just pass parameters to another function, and return whatever that
+ other function returned, without having to include the return's /
+ parameters' type header.
+
+ Try it out here: godbolt.org/g/oV8G5Q
+
+ * wtf/Forward.h:
+
2018-03-29 JF Bastien <[email protected]>
Use Forward.h instead of forward-declaring WTF::String
Modified: trunk/Source/WTF/wtf/Forward.h (230108 => 230109)
--- trunk/Source/WTF/wtf/Forward.h 2018-03-30 17:30:18 UTC (rev 230108)
+++ trunk/Source/WTF/wtf/Forward.h 2018-03-30 17:36:20 UTC (rev 230109)
@@ -114,3 +114,51 @@
template<class T, class E> using Expected = std::experimental::expected<T, E>;
template<class E> using Unexpected = std::experimental::unexpected<E>;
+
+// Sometimes an inline method simply forwards to another one and does nothing else. If it were
+// just a forward declaration of that method then you would only need a forward declaration of
+// its return types and parameter types too, but because it's inline and it actually needs to
+// return / pass these types (even though it's just passing through whatever it called) you
+// now find yourself having to actually have a full declaration of these types. That might be
+// an include you'd rather avoid.
+//
+// No more. Enter template magic to lazily instantiate that method!
+//
+// This macro makes the method work as if you'd declared the return / parameter types as normal,
+// but forces lazy instantiation of the method at the call site, at which point the caller (not
+// the declaration) had better have a full declaration of the return / parameter types.
+//
+// Simply pass the forward-declared types to the macro, with an alias for each, and then define
+// your function as you otherwise would have but using the aliased name. Why the alias? So you
+// can be lazy on templated types! Sample usage:
+//
+// struct Foo; // No need to define Foo!
+// template<typename T>
+// struct A {
+// Foo declared(Bar); // Forward declarations of Foo and Bar are sufficient here.
+// // The below code would normally require a definition of Foo and Bar.
+// WTF_LAZY_INSTANTIATE(Foo=Foo, Bar=Bar) Foo forwarder(Bar b) { return declared(b); }
+// };
+#define WTF_LAZY_JOIN_UNLAZE(A, B) A##B
+#define WTF_LAZY_JOIN(A, B) WTF_LAZY_JOIN_UNLAZE(A, B)
+#define WTF_LAZY_ARGUMENT_NUMBER(_1, _2, _3, _4, _5, _6, _7, N, ...) N
+#define WTF_LAZY_REVERSE_SEQUENCE() 7, 6, 5, 4, 3, 2, 1, 0
+#define WTF_LAZY_NUM_ARGS_(...) WTF_LAZY_ARGUMENT_NUMBER(__VA_ARGS__)
+#define WTF_LAZY_NUM_ARGS(...) WTF_LAZY_NUM_ARGS_(__VA_ARGS__, WTF_LAZY_REVERSE_SEQUENCE())
+#define WTF_LAZY_FOR_EACH_TERM(F, ...) \
+ WTF_LAZY_JOIN(WTF_LAZY_FOR_EACH_TERM_, WTF_LAZY_NUM_ARGS(__VA_ARGS__))(F, (__VA_ARGS__))
+#define WTF_LAZY_FIRST(_1, ...) _1
+#define WTF_LAZY_REST(_1, ...) (__VA_ARGS__)
+#define WTF_LAZY_FOR_EACH_TERM_0(...)
+#define WTF_LAZY_FOR_EACH_TERM_1(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_0(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_2(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_1(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_3(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_2(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_4(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_3(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_5(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_4(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_6(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_5(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_FOR_EACH_TERM_7(F, ARGS) F(WTF_LAZY_FIRST ARGS) WTF_LAZY_FOR_EACH_TERM_6(F, WTF_LAZY_REST ARGS)
+#define WTF_LAZY_DECLARE_ALIAS_AND_TYPE(ALIAS_AND_TYPE) typename ALIAS_AND_TYPE,
+#define WTF_LAZY_INSTANTIATE(...) \
+ template< \
+ WTF_LAZY_FOR_EACH_TERM(WTF_LAZY_DECLARE_ALIAS_AND_TYPE, __VA_ARGS__) \
+ typename = void>