Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does std::declval work?

Tags:

c++

c++11

Can somebody explain how does std::declval work? I've found this implementation inside gcc headers/type_traits (lines 2248-2262), which is (cleared up a bit to improve readability):

template<typename _Tp>
struct __declval_protector
{
    static const bool __stop = false;
    static typename add_rvalue_reference<_Tp>::type __delegate();
};

template<typename _Tp>
typename add_rvalue_reference<_Tp>::type
declval ()
{
    static_assert(__declval_protector<_Tp>::__stop, "declval() must not be used!");
    return __declval_protector<_Tp>::__delegate();
}

I don't understand the part return __declval_protector<_Tp>::__delegate(), does it call the default initializer for an Rvalue reference of type T? Also i don't understand why the static_assert is not called every time I call declval, since __stop is always false (And how can it distinguish between unevaluated contexts and evaluated ones?).

EDIT: From what I understand now, all this stuff is equivalent to:

template<typenam _Tp>
struct __declval_protector
{
    const bool __stop = false;
};

template<typename _Tp>
typename add_rvalue_reference<_Tp>::type
mydeclval ()
{
    static_assert(__declval_protector<_Tp>::__stop, "declval() must not be used!");
}

But of course the compiler will issue that we do not return anything.

like image 605
Mattia F. Avatar asked Dec 02 '22 14:12

Mattia F.


1 Answers

I don't understand why the static_assert is not called every time I call declval, since __stop is always false

Your premise is wrong. The static assert is indeed called every time you call declval. The trick is that you must never call declval. It must only be used in unevaluated contexts. That's why the static assertion is there.

like image 160
Kerrek SB Avatar answered Dec 21 '22 09:12

Kerrek SB