C++ Logo

std-discussion

Advanced search

Re: Separate headers for declaration and constexpr definition of the same function

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sat, 03 Jun 2023 10:02:49 +0100
On Fri, 2023-06-02 at 13:33 -0700, Thiago Macieira via Std-Discussion
wrote:
> On Friday, 2 June 2023 01:24:11 PDT Lénárd Szolnoki via Std-
> Discussion wrote:
> > I am trying to come up with a pattern that would allow me to have
> > the
> > declaration and definition of a constexpr function in separate
> > headers.
> > The function would need to be explicitly instantiated in a
> > dedicated
> > translation unit.
>
> Use if consteval or if (std::is_constant_evaluated()) and then
> dispatch to
> another function.
>
> > The idea is that users that don't need the constexpr functionality
> > could include square.h instead of square_constexpr.h , possibly
> > saving
> > some compile time if square_constexpr.h is much heavier (it could
> > contain a lot of other additional includes).
> >
> > Unfortunately doing this with the pattern above is ill-formed, as
> > constexpr makes the function implicitly inline[1], and inline
> > functions
> > must be defined in the same TU they are used[2], I see no
> > exemptions
> > for function templates. Interestingly I merely get a warning in gcc
> > and
> > clang, and no warning or error on MSVC. According to [2], this
> > should
> > be strictly ill-formed, not IFNDR.
>
> Even if said function is never called?
>
> This compiles:
> constexpr int cfunc(int);
> constexpr int func(int x)
> {
> if consteval {
> return cfunc(x);
> }
> return x;
> }
>
> But produces a warning with Clang and GCC. The question is whether
> the warning
> is reasonable because of something the standard says or if we can
> force the
> compilers to shut up.

If done with std::is_constant_evaluated(), this would still fall under
https://eel.is/c++draft/basic.def.odr#12.sentence-2, as the call cfunc
is odr-use of cfunc.

I believe it's technically odr-use even within if consteval, but I'm
less sure about that. That would make this ill-formed and compilers
accepting this are implementing an extension.

I think both your and my pattern should be accepted. Having said that I
would prefer if my pattern could be fixed with a DR, as it's applicable
in C++17 and possibly before, while if consteval would require C++23.
The definition of odr-use can't be changed under `if
(std::is_constant_evaluated())`, so your pattern is not applicable in
C++20 and would require if consteval.

I think ideally https://eel.is/c++draft/basic.def.odr#12.sentence-2
should be much less strict and there should be explicit instantiation
declaration/definition syntax for all kind of entities that normally
produce a weak symbol (so inline functions/variables and variable
templates in addition to function and class templates). Then neither
dummy template parameters or jumping through if consteval would be
necessary.

Cheers,
Lénárd

Received on 2023-06-03 09:02:54