我的代码的一个最小化示例显示了这个问题:
#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";
......它起作用了。
3条答案
按热度按时间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
。请注意,成功。若要移除cv限定词,请使用
remove_cv_t
。在你的最后一个片段里
b
不是常数,所以decltype(b)
实际上是bool
,而不是const bool
。jgwigjjp2#
密钥是
const
,因此您需要删除它以使Assert通过。zaq34kh63#
所以
decltype(key)
是const bool
,而不是bool
你用
const auto&
捕捉它所以它是const
typeid
删除所有cvref限定符,这就是为什么您会得到相同hash_code
作为一个附带说明,
hash_code
是一个 hash,并且不保证它们不会冲突,您可以使用operator==
来检查类型是否相等。