jeudi 1 septembre 2016

Is std::declval

As far as I know, I cannot declare an rvalue reference to void.
As an example, the following code is ill-formed:

 void f(void &&v) { }

From [20.2.6/1] (function template declval) we have a declaration for declval that is:

template <class T>
add_rvalue_reference_t<T>
declval() noexcept;

Thus, declval<void> (let me say) would result in void &&, that I guessed it was ill-formed as well as in the previous example.

Anyway, the following minimal, working example compiles:

#include<utility>

int main() {
    decltype(std::declval<void>)* ptr = nullptr;
}

Note that the following is true too:

static_assert(std::is_same<decltype(std::declval<void>()), void>::value, "!");

I would have expected it to be void&& as previously mentioned (or better, I was expecting it fails to compile).
Actually, it happens to be an rvalue reference for any other non-reference type.
As an example:

static_assert(std::is_same<decltype(std::declval<int>()), int&&>::value, "!");

Is declval<void> a valid expression or not? Is the code above legal?
Why does the behavior in case of void is different than with any other type? (For it wouldn't have worked otherwise could be an answer, if the code is legal).

If it's legal, where does the standard allow that? I've not been able to find the case.
Of course, the standard says:

The template parameter T of declval may be an incomplete type.

Anyway, here it would result in a non acceptable type (void&&) and it works around it discarding the rvalue reference.

Aucun commentaire:

Enregistrer un commentaire