Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11: constness in perfect forwarding

Tags:

c++

c++11

I created function to detect the constness and l(r)valueness of the argument.

template<class T> std::string
detect(typename std::remove_reference<T>::type&&) {
    return std::string(std::is_const<T>::value ? "const " : "") + "rvalue";
}
template<class T> std::string
detect(typename std::remove_reference<T>::type&) {
    return std::string(std::is_const<T>::value ? "const " : "") + "lvalue";
}

for some reason, is_const always returns false even on const types, for example const int&. I tried adding another overload to capture the constness

template<class T> std::string
detect(const typename std::remove_reference<T>::type& ) { return "const lvalue"; }

compiler then complains that detect is ambiguous when applied to const int&. So I think the compiler has correct figure out T=const int&, but why doesn't is_const return true?

like image 429
Candy Chiu Avatar asked Oct 22 '25 09:10

Candy Chiu


1 Answers

std::is_const<T> only detects top-level const. Like foo const, or foo* const. It doesn't care about "inner" consts, like foo const* or foo const&.

If what you want is to see if type a reference to const, you need to take out the reference first, so the const becomes top-level:

std::is_const<typename std::remove_reference<T>::type>::value

In any case, the functions shown do not allow type deduction, meaning you have to pass T explicitly, like detect<foo const&>(x). Maybe you want something like the following?

template<class T> std::string
detect(T&&) { // have T be deduced
    return std::string(std::is_const<typename std::remove_reference<T>::type>::value ? "const " : "")
         + (std::is_lvalue_reference<T>::value? "lvalue" : "rvalue");
}

Which can be called like detect(x).

like image 175
R. Martinho Fernandes Avatar answered Oct 24 '25 22:10

R. Martinho Fernandes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!