Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Accessing variable template using decltype

A minimized example of my code showing the problem:

#include <cassert>
#include <iostream>
#include <map>
#include <string>

template <typename T>
const std::map<std::string, T> smap;

template <>
const std::map<std::string, bool> smap<bool>{{"a", false}};

int main() {
    std::map<bool, std::string> rmap{{false, "x"}};

    for (const auto& [key, val] : rmap) {
        std::cerr << typeid(bool).hash_code() << "\n";
        std::cerr << typeid(decltype(key)).hash_code() << "\n";

        std::cerr << smap<bool>.size() << "\n";
        std::cerr << smap<decltype(key)>.size() << "\n";

        assert((std::is_same_v<bool, decltype(key)>));
    }

    return 0;
}

Godbolt

It gives the output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

10838281452030117757
10838281452030117757
1
0
example.cpp:22: int main(): Assertion `(std::is_same_v<bool, decltype(key)>)' failed.

Why is it that I can’t access the variable template using decltype when it’s referring to the same type (bool)?

For the record I also tried to not use structured binding and using decltype on first in the pair with the same result.

However if I create an actual bool variable, like so …

bool b;
std::cerr << settings_map<decltype(b)>.size() << "\n";

… it’s working.

>Solution :

decltype(key) is const bool, not bool. And typeid strips const qualifiers, so the two have the same (runtime) representation.

If the type of type or expression is cv-qualified, the result of the typeid refers to a std::type_info object representing the cv-unqualified type (that is, typeid(const T) == typeid(T)).

So while typeid treats the two types as equivalent, template expansion (and is_same_v) does not, and you get two different maps: one for bool and one for const bool. Note that the assertion

assert((std::is_same_v<const bool, decltype(key)>));

succeeeds if put in place of the one in your code. To remove cv-qualifiers, use remove_cv_t.

std::cerr << settings_map<std::remove_cv_t<decltype(key)>>.size() << "\n";

In your last snippet

bool b;
std::cerr << settings_map<decltype(b)>.size() << "\n";

The b is not constant, so decltype(b) is actually bool, not const bool.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading