[cfe-dev] RFC: A mechanism for importing a declaration only when it exists

Louis Dionne via cfe-dev cfe-dev at lists.llvm.org
Fri Jun 26 12:49:41 PDT 2020



> On Jun 26, 2020, at 12:38, Arthur O'Dwyer <arthur.j.odwyer at gmail.com> wrote:
> 
> On Fri, Jun 26, 2020 at 5:34 AM David Chisnall via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
> On 26/06/2020 05:05, Louis Dionne via cfe-dev wrote:
> > Now, I understand this raises several questions. Of course, this couldn't be
> > done at the preprocessor level because I don't think we can know whether a
> > declaration exists at that time. However, I was curious to ask on this list
> > whether someone could think of a reasonable way to solve this problem.
> > 
> > Having some mechanism for doing this would be a huge life improvement for libc++.
> 
> I agree that something like this would be incredibly useful.  I wonder 
> if it's sufficient to provide a built-in type trait and write something 
> like:
> 
> using FILE = std::conditional<__type_exists_v<::FILE>, ::FILE, void>;
> 
> (With some built-in equivalent of std::conditional that does 
> short-circuit evaluation)  You'd still have the std::FILE type, but it 
> would be void on platforms where it didn't exist.
> 
> I agree with Whisperity that having "FILE = void" on some platforms would be a cure worse than the disease.
> It seems to me that what you want is less like an alias declaration and more like a using-declaration:

Indeed, I don't think FILE = void is a viable path forward. Also, it wouldn't work for things that aren't types, which is actually the vast majority of such using declarations (memcpy & friends, etc).

> 
>     namespace std {
>         __using_if_exists ::FILE;
>         __using_if_exists ::fopen;
>      }
> 
> This syntax would also match Louis's original intent better, since the thing it's replacing is literally a using-declaration, not an alias declaration.
> (I don't know off the top of my head whether there's a visible difference between `using ::T` and `using T = ::T`. I bet Richard knows. ;))
> 
> 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.
> 
> 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?

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.

> Bikeshed: __using_if_exists, __using_or_ignoring, __using_if_present, __using_unless_absent, __using_maybe_absent.
> 
> 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?

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.

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:

#if defined(__GNUC__)
#  define _LIBCPP_USING_IF_EXISTS(...) using __VA_ARGS__
#else
#  define _LIBCPP_USING_IF_EXISTS(...) __using_if_exists __VA_ARGS__
#endif

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.

Louis

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200626/e62da285/attachment-0001.html>


More information about the cfe-dev mailing list