flau
flau

Reputation: 1380

How do I check whether a reference is const?

I was writing a test for my iterator types and wanted to check that the reference returned by de-referencing iterators provided by begin() and cbegin() are non-const and const respectively.

I tried doing something similar to the following : -

#include <type_traits>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec{0};

    std::cout << std::is_const<decltype(*vec.begin())>::value << std::endl;
    std::cout << std::is_const<decltype(*vec.cbegin())>::value << std::endl;
}

But this prints 0 for both cases.

Is there a way to check if a reference is const?

I can use C++11/14/17 features.

Upvotes: 7

Views: 1397

Answers (4)

einpoklum
einpoklum

Reputation: 131626

*it will be a reference rather than the referenced type (int& or const int& rather than int or const int in your case). So, you need to remove the reference:

#include <iostream>
#include <type_traits>
#include <vector>

int main() {
    std::vector<int> vec{0};

    std::cout << std::is_const<std::remove_reference<decltype(*vec.begin())>::type>::value << std::endl;
    std::cout << std::is_const<std::remove_reference<decltype(*vec.cbegin())>::type>::value << std::endl;
}

This produces:

0
1

Note: The above works uses C++11. @eerorika's answer is more terse, but requires C++17.

Upvotes: 5

yelliver
yelliver

Reputation: 5926

You can check the notes on document here: https://en.cppreference.com/w/cpp/types/is_const

  • Notes

If T is a reference type then is_const::value is always false. The proper way to check a potentially-reference type for const-ness is to remove the reference: is_const::type>.

for(auto it=vec.begin(); it!=vec.end(); ++it) {
    std::cout << std::is_const<std::remove_reference<decltype(*it)>::type>::value << std::endl;
}

for(auto it=vec.cbegin(); it!=vec.cend(); ++it) {
    std::cout << std::is_const<std::remove_reference<decltype(*it)>::type>::value << std::endl;
}

Upvotes: 2

Acorn
Acorn

Reputation: 26076

is_const always returns false for references. Instead, do:

std::is_const_v<std::remove_reference_t<decltype(*v.begin() )>> // false
std::is_const_v<std::remove_reference_t<decltype(*v.cbegin())>> // true

Upvotes: 3

eerorika
eerorika

Reputation: 238351

Remove the reference to get the referenced type to inspect its constness. A reference itself is never const - even though references to const may colloquially be called const references:

std::is_const_v<std::remove_reference_t<decltype(*it)>>

Upvotes: 7

Related Questions