编译器是如何从map中找出模板类型的
how did the compiler figure out the template types from map
我是一个使用模板的胆小用户,通常遵循常规的示例案例。
因此,看到以下代码,我感到非常惊讶。
template<typename Table> void set(Table& tbl,
const typename Table::key_type& key,
const typename Table::mapped_type& attr)
{
typename Table::iterator iter = tbl.find(key);
if (iter != tbl.end()) {
iter->second = attr;
} else {
typedef typename Table::key_type TableKey;
typedef typename Table::mapped_type TableNonKey;
tbl.insert( std::pair<TableKey,TableNonKey>(key,attr) );
}
}
template<typename Table> void show(Table& tbl)
{
for (typename Table::iterator iter = tbl.begin();
iter != tbl.end(); ++iter) {
cout << iter->second << endl;
}
}
int main(){
std::map<int, int> table_obj;
set(table_obj, 1, 2);
show(table_obj);
}
在编译show/set函数时,编译器如何知道Table是std::map,并能够从中推导出Table::key_type和Table::mapped_type?模板还有其他类似的用例吗?
在main
中,编译器知道"table"的类型,然后使用Koenig Lookup/ADL在这种情况下找到一个合适的set
,因为只有一个。
申报
template<typename Table> void set(Table& tbl,
const typename Table::key_type& key,
const typename Table::mapped_type& attr);
实施
template<typename Table> void set(Table& tbl,
const typename Table::key_type& key,
const typename Table::mapped_type& attr) {
typename Table::iterator iter = tbl.find(key);
if (iter != tbl.end()) {
iter->second = attr;
} else {
typedef typename Table::key_type TableKey;
typedef typename Table::mapped_type TableNonKey;
tbl.insert( std::pair<TableKey,TableNonKey>(key,attr) );
}
}
CCD_ 3和CCD_ 4是来自std::map的typedef。
如果你这样叫"set"
std::vector<int> NotAMap;
set(NotAMap, 1, 2);
环回仍然会找到"set",并且在开始时发现Table可能是std::vector,但std::vector没有mapped_type
,所以它被拒绝作为候选者。
您的代码:
std::map<int, int> table_obj;
set(table_obj, 1, 2);
show(table_obj);
您的问题:
编译器如何知道Table是std::map并且能够推导out Table::key_type和Table::mapped_type编译show/set函数?
答:因为table_obj
的类型是已知的。
只要设身处地为编译器着想。在第1行中,您可以看到table_obj
是std::map<int, int>
。那么在第2行和第3行,你还应该做什么呢?只能用Table
=std::map<int, int>
实例化模板函数set
和show
。没有歧义。
如果你试图用其他类型实例化函数,就会出现错误:
set<double>(table_obj, 1, 2); // error
set<void>(table_obj, 1, 2); // error
set<std::map<int *, char *> >(table_obj, 1, 2); // error
set<std::map<double, int> >(table_obj, 1, 2); // error
set<std::map<int, int> >(table_obj, 1, 2); // OK
正如您所看到的,指定类型是冗余。因此C++允许您省略它。
该语言的这一功能被称为模板参数推导。
模板还有其他类似的用例吗?
几乎每一次使用标准算法。
考虑这个例子:
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v;
std::find(v.begin(), v.end(), 123);
}
如果没有模板参数推导,最后一行必须写成:
int main()
{
std::vector<int> v;
std::find<std::vector<int>::iterator, int>(v.begin(), v.end(), 123);
}
相关文章:
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 类型为 'std::map< char,int > 的 <Swig 对象的代理
- std::map 保存任何值类型
- 标准::map键类型的严格弱排序概念
- 如何在 Visual C++ 中从返回类型为 map 的函数返回 null?
- 在变量名后声明带有 () 的非内部类型与不使用变量名的行为不同。即 std::map<int,char>x(); - 这是怎么回事?
- 将参数列表未知的可变参数模板类型定义为 std::map 值类型
- 不完整的类型为 std::map 的成员
- 当 map 是一个整数数组并且由 operator[] 创建时,它是否初始化其映射类型
- 具有 std::map 和 std::variant 的不完整类型
- 如何在 c++ 中使用返回类型导出函数 std::map
- 错误:与'operator='不匹配(操作数类型为"std::map<int、double>::iterator
- 为什么C++允许类型没有 std::map 的默认构造函数,而没有 std::p air
- 将QML数组和MAP/对象类型与C 区分开
- std::map使用不同的数据类型进行值
- 为什么缩小转换范围不能防止错误类型的map.insert()失败
- Qt nmake:错误 C3203:"map":非专用类模板不能用作模板参数"base"的模板参数,预期为真实类型
- 无法使用 std::map 推断 lambda 的返回类型
- 如何打印这种类型map的值map
, int>关联[2]