C++ Logo

std-proposals

Advanced search

Re: std::is_constexpr_constructible (/ std::is_constexpr)

From: Michael Scire <sciresm_at_[hidden]>
Date: Sat, 23 Oct 2021 12:57:55 -0700
> if constexpr (requires { []<int>(){}.template operator()<(T(args...),
void(), 0)>(); })

This appears to work and is much better than what I came up with, thank you.

It has the same limitation that args must be passable as NTTP (motivating a
macro for constexpr values which cannot be used as NTTPs), but this is an
improvement and I appreciate it.

> Can you give more details and an actual, small example of what the
comments would actually be? I'm having trouble visualising what code would
exist that depends on an unknown type's ability to be constructed
constexprly.
> In other words, can you give more details on what this functionality
would enable?

Sure.

The actual context where I needed it was for a slab heap which uses CRTP
for objects with a common base.

The class looks a little like:

template<typename Derived, typename Base> requires std::derived_from<Base,
BaseObject>
class SlabAllocatable : public Base {
    private:
        static constinit inline SlabHeap<Derived> s_slab_heap;
    public:
        // ...
        static Derived *Create();
};

A class which uses this would look something like:

class MyObject : public SlabAllocatable<MyObject, BaseObject> { /* ... */ };

The objects which can use this template all share a common base class, and
this base class has a virtual method to retrieve an integer class token.

i.e. BaseObject has virtual ClassTokenType GetClassToken() = 0;

The base class has a member field to cache the class token. Doing this
enables class token retrieval from BaseObject* without having to make any
virtual calls, by returning m_ClassTokenCache.

I would like to set the class token cache in the base class constructor,
but this is not possible because a base class cannot call derived class
virtual functions until the derived class constructor has finished.

My desired usage for is_constexpr_constructible looks something like:

template<typename Derived, typename Base>
Derived *SlabAllocatable::Create() {
        Derived *obj = Allocate(); // obj has been fully constructed here,
and has m_ClassTokenCache = 0;
        if constexpr (is_constexpr_constructible_v<Derived>) {
            constexpr ClassTokenType ClassToken = d{}.GetClassToken(); //
Valid if d is constexpr constructible and has constexpr virtual
implementation of GetClassToken().
            obj->InitializeClassTokenCache(ClassToken); // This sets the
class token cache without having to perform a virtual call at runtime.
        } else {
            obj->InitializeClassTokenCache(obj->GetClassToken()); // This
performs a virtual call in the process of getting the class token.
        }
        return obj;
}

In particular, knowing whether or not an object is constexpr-constructible
would enable me to attempt to construct one and retrieve its class token
via the GetClassToken() method, preventing the need for the virtual call.

Without the if constexpr construction, trying to get the class token would
result in a compiler-error in the case where it's not possible.

I have thought about e.g. if constexpr (requires {
Derived::GetClassTokenStatic(); }), but this causes there to be more than
one source of truth for an object's token, which seems undesirable.

I did see while searching some other, related use cases for checking
constexpr-evaluability:
https://stackoverflow.com/questions/55288555/c-check-if-statement-can-be-evaluated-constexpr

I have wanted this kind of introspection in a number of other contexts, as
well. Hopefully the above is clarifying.

Best,
Michael Scire


On Sat, Oct 23, 2021 at 8:21 AM Thiago Macieira via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Saturday, 23 October 2021 00:27:30 PDT Michael Scire via Std-Proposals
> wrote:
> > In particular, a common use case might be like:
> >
> > ```
> > if constexpr (std::is_constexpr_constructible<T>::value) {
> > constexpr T t{/* potentially arguments here */};
> > // Use t as a non-type-template parameter, or use it in other
> > compile-time only ways like for static asserts.
> > } else {
> > T t{/* potentially arguments here */};
> > // Use t as a runtime value.
> > }
> > ```
>
> Can you give more details and an actual, small example of what the
> comments
> would actually be? I'm having trouble visualising what code would exist
> that
> depends on an unknown type's ability to be constructed constexprly.
>
> In other words, can you give more details on what this functionality would
> enable?
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel DPG Cloud Engineering
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2021-10-23 14:58:12