2

recently I was wondering about how a metafuntion like declval is implemented.

The first thing I tried myself was:

template <typename T>
constexpr auto declval() -> T&&;

this as such was working fine, except that when I was trying to use it to create varialbe (makes no sense right now , I know) I was getting linker error, which is obvious, as there is no body for the function.

auto varName = declval<int>(); // linker error
decltype(declval<int>()) varName2 = 5; // works fine

I though, whether the original implementation (as of gcc version) will behave the same way (giving me the linker error). It turned out, that their implementation of the declval when trying to use to create variable does static assertion looking more or less like:

static_assert(__declval_protector<T>::stop, "error message");

That was surprising to me. I wanted to achieve the exact same behavior. My first attempt went like:

template <typename T>
auto declval() -> T&&{static_assert(false, "error message")}

I thought, that maybe when declval is used in decltype context, then it's body is not needed at all, so maybe compiler will skip it and in case I was trying to create variable it will do static_assert, since declval body is crucial thing

That was not true. I was always getting static_assert error and could not compile any program with declval usage. I thought I will try to implement it more or less the same way as in the standard library. Finally with help of my colleagues we came to the following implementation:

template <typename T>
struct Protector{
    const static bool stop=false;
};

template <typename T>
constexpr auto declval() -> T&&
{
    static_assert(Protector<T>::stop, "You cannot do it");
}

And this was working totally fine. Exactly the same way as the standard library version. But why this is working is totally misterious to me.

Could anyone explain me how is the second implementation working in the C++? For me it should do same static_assert error as in case of decltype context, but apparently it does not.

What's the reason the implementations behave differently.

DawidPi
  • 2,285
  • 2
  • 19
  • 41

0 Answers0