0

I was working a little on this code:

#include <type_traits>

template<typename T, typename T2>
constexpr bool Assignable = std::is_assignable<T&,T2>::value;

template<typename T>
void test() {
    static_assert(Assignable<T, std::string>, "hello1");
    static_assert(Assignable<T&, std::string>, "hello2");
}

int main()
{
    test<int>();
}

I wonder what static_assert(Assignable<T&, std::string>, "hello2"); checks exactly?

Since Assignable already uses T& inside, calling static_assert(Assignable<T, std::string>, "hello1"); should check if reference to type T is assignable with std::string. I wonder what T& inside static_assert(Assignable<T&, std::string>, "hello2"); does?

Regards

bartop
  • 9,971
  • 1
  • 23
  • 54
Afshin
  • 8,839
  • 1
  • 18
  • 53

1 Answers1

2

Due to reference collapsing rules, this:

static_assert(Assignable<T&, std::string>, "hello2");

is logicaly equivalent to code like this one:

static_assert(Assignable<T, std::string>, "hello2");

Why? Long story short - lvalue reference to lvalue reference collapses to lvalue reference.

bartop
  • 9,971
  • 1
  • 23
  • 54
  • thanks. I knew this condition happens sometimes, but I didn't know exactly when. But as a side question, is there any benefit to keep `&` inside `static_assert(Assignable, "hello2");`? – Afshin Aug 22 '19 at 14:46
  • I don't think so, I believe that with this definition of `Assignable` trait, the second check can and should be removed – bartop Aug 22 '19 at 14:48