C++ Logo

std-proposals

Advanced search

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

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sat, 23 Oct 2021 10:29:10 +0100
Hi,

Needing actual objects of type Args... is something fundamentally needed here. If an invocation of a function is constant expression or not generally depends on the values of the arguments too, even if the selected function is marked constexpr.

Cheers,
Lénárd


-------- Original Message --------
From: Michael Scire via Std-Proposals <std-proposals_at_[hidden]>
Sent: October 23, 2021 8:27:30 AM GMT+01:00
To: sotrdg sotrdg via Std-Proposals <std-proposals_at_[hidden]>
Cc: Michael Scire <sciresm_at_[hidden]>
Subject: [std-proposals] std::is_constexpr_constructible (/ std::is_constexpr)

Hi,

I find myself somewhat often wanting to have function behavior differ
depending on whether or not an action can be performed at compiletime or
not.

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.
    }
```

I needed to implement this recently and found it very, very hard to do so.
The language doesn't seem to expose any clean way to detect whether an
action can be performed at compile-time without a compile-error in the
false case.

I eventually implemented based on overloading/SFINAE (see here:
https://godbolt.org/z/bvb1vqxjc) but my implementation has a number of
fundamental deficiencies that seem impossible to work around to me without
magic compiler help.

In particular, to test that type T can be constructed with argument types
Args... I need to actually have instances (not std::declval<>) of Args at
compile-time, and it is difficult to do this in many cases (particularly
for non-default-constructible types which cannot be passed as NTTPs).

I am imagining adding to <type_traits> the following:

template<class T, class... Args>
struct is_constexpr_constructible;

template<class T, class... Args>
struct is_constexpr_constructible_v = is_constexpr_constructible<T,
Args...>::value;

This would behave like
std::is_constructible/std::is_move_constructible/etc, indicating whether or
not it is possible to construct an object at compile-time.

There is also the obvious suggestion of e.g.
std::is_constexpr_move_constructible, std::is_constexpr_copy_constructible
etc...

However, it may be simpler to generalize further, and e.g. have some
template like std::is_constexpr which tells you whether or not a function
was declared with the constexpr keyword, or std::is_constexpr_invocable
which would return true if the function could be invoked at compile-time.

Generally, I think it would be very nice for the language to expose the
constexpr-status of functions the way that it does noexcept/const/etc.

Received on 2021-10-23 04:29:21