lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] constexpr conversion functions


From: Vadim Zeitlin
Subject: Re: [lmi] constexpr conversion functions
Date: Mon, 1 Aug 2022 17:59:44 +0200

On Mon, 1 Aug 2022 15:31:25 +0000 Greg Chicares <gchicares@sbcglobal.net> wrote:

GC> On 7/23/22 15:41, Vadim Zeitlin wrote:
GC> [...]
GC> >  First, and trivially, you should sprinkle magic constexpr dust all over
GC> > your code, i.e. declare ambiguous conversion operators
GC> 
GC> I'd like to ask a question about the ambiguous conversion operators only.
GC> 
GC> > and all the
GC> > functions (equiplausible_construct, equiplausible_assign, c_moveable,
GC> > a_moveable) as constexpr, as this is needed to allow using static_assert<>
GC> > with them. You could also make sandbox_test a compile-only test if you
GC> > replaced all LMI_TEST() in it with static_assert<>s.
GC> [...]
GC> > template<typename T>
GC> > struct ambiguator {
GC> >     constexpr operator T const&();
GC> >     constexpr operator T&&();
GC> > };
GC> 
GC> If I make all the other changes you suggest, but don't make the two
GC> ambiguous conversion operators 'constexpr', then all the static_assert<>ed
GC> tests pass, and neither gcc nor clang complains. My question is whether
GC> it's still better to make them 'constexpr'. (I will do so anyway; I'm
GC> just trying to understand the rules and their consequences.)

 Sorry, I have to admit that I'm not really sure. I'm, of course, not at
all an expert in constexpr-ness, and my usual approach is summarized pretty
exactly in my advice above: i.e. I try to add constexpr everywhere and then
remove it from places where the compiler complains that it can't be used.
I do this because I believe -- perhaps wrongly -- that constexpr can never
do any harm (in the places where it is allowed) and it has some tangible
benefits: not only it can result in faster code due to the function being
evaluated at compile-time, but it also detects undefined behaviour at
compile-time as well.

 In this particular case, both points are moot, of course, as the functions
are never going to be called and there can't be any undefined behaviour in
them as they're not even defined. So it's hard to see any benefit in making
them constexpr and even though I don't see any real problems with doing it
neither, it's probably better _not_ to do it, just because the concept of
an undefined constexpr function doesn't really make sense. In fact, because
constexpr implies inline, a constexpr function without a definition is
already suspicious (even if allowed).

 So, to summarize, in this particular case my auto-pilot approach to
constexpr seems to have led me (but not you!) astray and it indeed
shouldn't be used here.

GC> The only reason not to do that is a fear that adding 'constexpr' might
GC> cause them not to work as intended, in some context that I can't imagine.

 I can't imagine such context neither. But I can imagine that using
constexpr here being seen as confusing.

GC> I searched the entire [class.conv] section of C++20, and it never uses
GC> the word 'constexpr'. At first, that seemed striking: if it's a good idea,
GC> why don't they mention it? But then I figured that they don't mention it
GC> because there's no need: non-constexpr-ness would arise in conversion
GC> functions in the same way as in any other function;

 Yes, I don't think there is anything particular about constexpr and
conversion functions, it works with them in the same way as with all the
other functions.

GC> Let me put that question in a different way: if I were to report this as
GC> a defect,

 Sorry, but what exactly would you report as a defect? Surely a compiler
can't possibly propose adding a constexpr to a function without a
definition and what else could/would you expect? I feel like I'm missing a
step here, sorry in advance if I just overlooked something, but could you
please explain again what do you think the defect is?

 Thanks!
VZ

Attachment: pgpEQFU4ZEWqp.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]