c++ 使用decltype访问变量模板

dl5txlt9  于 2022-12-05  发布在  其他
关注(0)|答案(3)|浏览(159)

我的代码的一个最小化示例显示了这个问题:

#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
输出如下:

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

当变量模板引用相同的类型(bool)时,为什么我不能使用decltype访问变量模板?
为了记录在案,我还试图不使用结构化绑定,并在对中的第一个上使用decltype,结果相同。
然而,如果我创建一个实际的bool变量,就像这样...

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

......它起作用了。

thtygnil

thtygnil1#

decltype(key)const bool,而不是bool。并且typeid去掉了const限定符,因此两者具有相同的(运行时)表示。
如果型别或运算式的型别是cv限定的,typeid的结果会指涉表示cv非限定型别(亦即typeid(const T) == typeid(T))的std::type_info对象。
因此,虽然typeid将这两种类型视为等同的,但模板扩展(和is_same_v)却不是这样,您会得到两个不同的Map:一个用于bool,另一个用于const bool。请注意,

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

成功。若要移除cv限定词,请使用remove_cv_t

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

在你的最后一个片段里

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

b不是常数,所以decltype(b)实际上是bool,而不是const bool

jgwigjjp

jgwigjjp2#

密钥是const,因此您需要删除它以使Assert通过。

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

zaq34kh63#

所以decltype(key)const bool,而不是bool
你用const auto&捕捉它所以它是const
typeid删除所有cvref限定符,这就是为什么您会得到相同hash_code
作为一个附带说明,hash_code是一个 hash,并且不保证它们不会冲突,您可以使用operator==来检查类型是否相等。

相关问题