C++ Logo

std-proposals

Advanced search

[std-proposals] Fwd: unimplemented attribute

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 20 Mar 2025 10:09:14 -0400
---------- Forwarded message ---------
From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, Mar 20, 2025 at 10:07 AM
Subject: Re: [std-proposals] unimplemented attribute
To: Hans Åberg <haberg_1_at_[hidden]>


On Thu, Mar 20, 2025 at 5:46 AM Hans Åberg <haberg_1_at_[hidden]> wrote:
> > On 19 Mar 2025, at 18:52, Jason McKesson via Std-Proposals <std-proposals_at_[hidden]> wrote:
> >
> > On Wed, Mar 19, 2025 at 12:48 PM Hans Åberg via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> >>
> >>
> >>> On 19 Mar 2025, at 16:48, Andre Kostur via Std-Proposals <std-proposals_at_[hidden]> wrote:
> >>>
> >>> Not that I agree with the proposal, but the scenario I'm hearing:
> >>> 1) A cpp file includes a header with an [[unimplemented]] function
> >>> (say the modf example above)
> >>> 2) That cpp file then includes a header with the same function, but
> >>> this time without the [[unimplemented]] attribute
> >>> 3) The cpp file then calls that function.
> >>>
> >>> If one was to use =delete instead, #2 would be a compiler error as
> >>> that would be redeclaring the same function. And if #2 doesn't exist,
> >>> then the compilation could emit a diagnostic (before it got to the
> >>> link stage). Though I'm not yet sold that simply not declaring the
> >>> function at all isn't the better option anyway.
> >>
> >> This is just so as to not having to rely solely on linker errors and tables over what is so far implemented in the C++ version. If issuing a warning instead of an error, it will compile if the definition is in some other translation unit, though with a diagnostic message, which then can be suppressed by adding a declaration or a compiler option.
> >
> > I've been reading through this thread for a while, and it's very
> > unclear to me what "unimplemented" actually is intended to *mean*. I
> > understand what you mean for it to *do* in terms of how the compiler
> > can and cannot behave. But the intended meaning is... slippery.
> >
> > It seems to me that you want it to mean whatever the person compiling
> > the code wants it to mean for that compilation. Sometimes, it means
> > "calling this function is an error." But other times it means "calling
> > this function is fine; it's just not implemented here." And this
> > meaning doesn't live in the source code; it lives in the build system
> > and compiler options.
> >
> > What this ultimately means is that I cannot read a piece of code
> > including this attribute and have a clear understanding of exactly how
> > I can and cannot use that name. If I see `= delete`, that's very
> > clear: calling this function is an error. If I see `[[deprecated]]`,
> > that meaning is clear: you can call this now, but it may disappear in
> > later versions.
> >
> > But if I see `[[unimplemented]]`... does that mean I can call it or
> > not? What is the correct way to write code that uses (or doesn't use)
> > this function? And I'm not a fan of that answer being locked away
> > inside a build system.
>
> There are two parts, issue a compiler warning and the ability to write an override. Compiler writers may choose to say nothing, like GCC, or adding “delete”, like Clang:
>
> In the first case, one gets a compiler error that may hard to read if there is no declaration. In the float128_t example I gave, there will be for functions using it a long list of functions with other argument types, but no mentioning of the function one wants to use.
>
> If one adds a declaration there will be a linker error that may be hard to interpret.
>
> In these cases, one can write an override.
>
> Clang though chooses in some cases to use “delete”, and then one gets a compiler error which cannot be overridden.

You're explaining what behavior you want out of the build system. But
I'm asking what it *means* to a user. How I as a user should interpret
such a declaration.

If I see a function declaration, what that means is I expect to be
able to call that function with those parameters (unless it is
`delete`d). If I see an `[[unimplemented]]` declaration... can I call
it or not? If I'm not supposed to call it, then why is it there at
all? And if I am supposed to call it, why is the attribute there?

`[[deprecated]]` means "you can call this now, but you should not rely
on being able to do so in the future". I don't think we need the
reverse: "you cannot call this now, but you should be able to in the
future."

> > I don't know of any other C++ attributes where the intended meaning of
> > the code is determined by the build system. Yes, some compiler options
> > can change exactly how attributes work. But compiler options don't
> > change the meaning of `[[indeterminate]]`. A compiler could have an
> > option to fill such bytes in with known variables anyway, but the
> > meaning of that attribute is that my could *should not* be written
> > assuming those bytes have any particular value.
> >
> > If this attribute has different meanings in different contexts, and
> > I'm supposed to ask the build system what it actually means... then
> > it's probably not a good feature.
>
> The underlying semantic meaning is clear, to mark “unimplemented” on features not implemented, say on language features, and may suggest an effect, if giving any. But one may of course decide to choose something else in a compilation.

But if it's not implemented... *why is it there?* Can I call the
function or not? That's the question.

Received on 2025-03-20 14:09:28