Nir Friedman February 2016
### Constexpr decltype

I recently asked a question here (Detecting instance method constexpr with SFINAE) where I tried to do some constexpr detection at compile time. Eventually, I figured out that one can exploit `noexcept`

to do this: any constant expression is also `noexcept`

. So I put together the following machinery:

```
template <class T>
constexpr int maybe_noexcept(T && t) { return 0; }
...
constexpr bool b = noexcept(maybe_noexcept(int{}));
```

This works and `b`

is true as you'd expect, as zero-initializing an `int`

is a constant expression. It also correctly yields zero when it should (if I change `int`

to some other appropriate type).

Next, I wanted to check if something is `constexpr`

move constructible. So I did this:

```
constexpr bool b = noexcept(maybe_noexcept(int(int{})));
```

And again, this works properly for `int`

, or a user defined type. However, this checks that the type has both a constexpr default constructor and a constexpr move constructor. So, to work around this, I tried to change to declval:

```
constexpr bool b = noexcept(maybe_noexcept(int(declval<int>())));
```

This results in `b`

being false in gcc 5.3.0 (can't use clang for any of this, because clang does not correctly make constant expressions `noexcept`

). No problem, I say, must be because `declval`

is (interestingly enough) not marked `constexpr`

. So I write my own naive version:

```
template <class T>
constexpr T&& constexpr_declval() noexcept;
```

Yes, this is naive compared to how the standard library does it as it will choke on void and probably other things, but it's fine for now. So I try again:

`constexpr boo `

```
```

```
```

```
```### Answers

Yakk February 2016
`constexpr`

expressions must be defined. Yours is not defined, so in that case `int(constexpr_declval<int>())`

is not `constexpr`

.

Which means `maybe_noexcept(int(constexpr_declval<int>()))`

is not a `constexpr`

, so is not `noexcept`

.

And the compiler properly returns `false`

.

You also cannot invoke UB in a `constexpr`

.

I cannot think of a way to make a `constexpr`

reference to arbitrary data. I was thinking a `constexpr`

buffer of aligned storage reinterpreted as a reference to the data type, but that is UB in many contexts, hence not-`constexpr`

.

In general, this isn't possible. Imagine you had a class whose state determines if the method call is `constexpr`

:

```
struct bob {
int alice;
constexpr bob(int a=0):alice(a) {}
constexpr int get() const {
if (alice > 0) throw std::string("nope");
return alice;
}
};
```

now, is `bob::get`

`constexpr`

or not? It is if you have a `constexpr bob`

constructed with a non-positive `alice`

, and ... it isn't if not.

You cannot say "pretend this value is `constexpr`

and tell me if some expression is `constexpr`

". Even if you could, it wouldn't solve the problem in general, because the *state* of a `constexpr`

parameter can change if an expression is `constexpr`

or not!

Even more fun, `bob().get()`

*is constexpr*, while `bob(1).get()`

is not. So your first attempt (default construct the type) even gave the wrong answer: you can test, then do the action, and the action will fail.

The object is effectively a parameter to the method, and without the state of al parameters, you cannot determine if a function is `constexpr`

.

The way to det

```
```#### Post Status

Asked in February 2016

Viewed 3,724 times

Voted 4

Answered 1 times
#### Search

## Leave an answer

```
```

```
```