<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><br class="">In any case, I concur with Louis that this seems like it'd have to be done at the C++ level, not the preprocessor level.<br class=""><br class="">The semantics of my hypothetical "__using_if_exists QUALNAME;" declaration are that it does a name lookup on QUALNAME, and then if the lookup fails it does nothing, and if the lookup succeeds it acts like a regular `using` declaration. This feels like it should be super easy to implement as a compiler extension, right?<br class=""></blockquote><br class="">Yes, that's exactly what I was asking. I wondered whether folks could spot a fundamental issue with doing this, but it looks like perhaps there is none.<br class=""><br class=""><blockquote type="cite" class="">Bikeshed: __using_if_exists, __using_or_ignoring, __using_if_present, __using_unless_absent, __using_maybe_absent.<br class=""><br class="">But, doesn't libc++ also need to work with GCC and maybe other compilers too? So won't you need to convince those compilers to implement whatever you pick here, or else keep the existing preprocessor hacks around forever anyway?<br class=""></blockquote><br class="">AFAICT, libc++ works with recent-ish GCCs and Clang, that's it. There's been some work for it to work on other compilers, but none of it is maintained, and all of it is probably broken -- as far as I'm aware.<br class=""><br class="">If we went down that route, I'd kindly ask GCC to implement the same builtin, and if they say no, I could always resort to:<br class=""><br class="">#if defined(__GNUC__)<br class="">#  define _LIBCPP_USING_IF_EXISTS(...) using __VA_ARGS__<br class="">#else<br class="">#  define _LIBCPP_USING_IF_EXISTS(...) __using_if_exists __VA_ARGS__<br class="">#endif<br class=""><br class="">Or whatever form that ends up taking. I might have to keep existing workarounds for a little bit, but it would be reasonable to require that this extension be supported in order to add support for a new platform. Otherwise the headers just become a huge spaghetti.<br class=""><br class="">Louis<br class=""><br class=""></div></div></blockquote></div><div><br class=""></div><div>It’s always best, when encountering issues like this, to solve them in the most generic way possible so that laypeople could benefit from our efforts as well.  That’s why I would favor solving this using reflection/reification techniques that we will want users to eventually be using anyway.  My original detailed reply from early this morning seems not to have gone through, looking at the thread online, so I’ll reproduce it here just to be sure it’s considered, since this is a perfect motivating case for these more general techniques.  Thanks and good luck,</div><div><br class=""></div><div>Dave</div><div><br class=""></div><div>My original reply:</div><div><br class=""></div><div>——</div><div><br class=""></div><div><div class="">I’ll take a shot.  About a year ago I developed what I call a "metaparse" statement node for clang, intended to work with a reflection implementation I developed alongside it, which in a sense brings preprocessor expansion ability into constexpr evaluation.</div><div class=""><br class=""></div><div class="">Assume for now __has_declaration is already defined:</div><div class=""><br class=""></div><div class="">```</div><div class="">consteval { //a "metaprogram"</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">  </span>if (__has_declaration(::FILE))</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">          </span>__queue_metaparse("using ::FILE;");</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>if (__has_declaration(::fpos_t))</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>__queue_metaparse("using ::fpos_t;");</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">       </span>if (__has_declaration(::size_t))</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>__queue_metaparse("using ::size_t;");</div></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">     </span>__queue_metaparse("static const int TestVar = 3;");</div><div class=""><br class=""></div><div class="">} //...queued metaparses performed here, placing parsed decls into outer scope...</div><div class=""><br class=""></div><div class="">static_assert(TestVar==3);</div><div class="">```</div><div class=""><br class=""></div><div class="">If you wanted to define __has_declaration via what I call my "mirror-image reflection" implem, rather than via a new built-in: you would first probably want to define a public clang::DeclContext method "bool hasDeclNamed(StringRef name)" to handle the lookup, then after building clang-wreflection that method would be available in all reflected DeclContexts.  Then:</div><div class=""><br class=""></div><div class="">```</div><div class="">#define __has_declaration(NAME) __clangreflexpr(::/*reflects the translation unit*/)->hasDeclNamed(#NAME)</div><div class="">```</div><div class=""><br class=""></div><div class="">The following is old code I have not updated in awhile, and the readme/documentation is a mess, but you'll get the gist.</div><div class=""><a href="https://github.com/drec357/clang-meta/" class="">https://github.com/drec357/clang-meta/</a></div><div class=""><br class=""></div><div class="">The reflection stuff did not catch on here because the clang folks did not want the clang AST interface to be exposed via reflection, as it is not stable.  But I was very surprised at least the metaparsing portion did not catch on — it’s a great general purpose tool that would work with any reflection implementation, or in other metaprogramming situations such as yours, and is dirt-simple to understand and use.  </div><div class=""><br class=""></div><div class="">FWIW Microsoft seemed to get the idea, and several months after my release added what they call "source generators" <a href="https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/" class="">https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/</a> to C# which seems to work in this way.  (See their sourceBuilder.append(…) stuff.  No attribution though :/).</div><div class=""><br class=""></div><div class="">Bottom line, to do these sorts of things in general we need reflection + its inverse ("reification" as some call it), and metaparsing or source generation or whatever you want to call seems to be the most straightforward and general solution for that latter task.</div><div class=""><br class=""></div><div class="">Hope that helps the brainstorming, good luck,</div><div class=""><br class=""></div><div class="">Dave</div></div></body></html>