为了个人教育,我正在编写一个哈希表的基本实现(尽管下面的内容可能与任何保存可以列表初始化的类型的容器有关),并希望尽我所能地使用c++的现代元素-特别是在这种情况下,完美转发。
在这样做的过程中,我发现我不能弄清楚一个特定的情况--编写一个插入函数,在接受一个括号括起的初始化程序列表的同时实现完美的转发。如果不这样写,就无法在尝试模拟std::unordered_map
(如插入样式container.insert({key,value})
)时使用完美转发。
具体地说,我有一些哈希表类,它将键和值存储为std::pair<T,U>
对象(例如)存储在向量中的bucket上的列表(对于哈希+链接的方法)
template<typename T,typename U, typename func = std::hash<T> >
class HashTable{
std::vector<std::list<std::pair<T,U> > > data;
...
public:
template<typename V>
bool insert(V &&entry)
{
//insert into the table by forwarding entry as
... = std::forward<V>(entry);
return true; //plus some logic for failed insertion if key already exists
}
};
然后,通过调用(如
std::pair<int32_t,std::string> example = {12,"bike"};
myHashTableObject.insert(example); //example 1
myHashTableObject.insert(std::pair<int32_t,std::string>(15,"car")); //example 2
myHashTableObject.insert({28,"bus"}); //example 3
示例1和2编译并工作正常,但示例3没有编译器错误(例如,使用第三个模板参数func
的默认类型-但错误与用户提供的哈希值类似)
error: no matching function for call to ‘HashTable<int, std::__cxx11::basic_string<char> >::insert(<brace-enclosed initializer list>)’
这似乎是合理的-它不能弄清楚如何解释初始化列表应该构造什么类型的对象。
一个简单的“解决方案”是忘记完美转发,只是重载insert
函数,以接受std::pair<T,U>
的右值引用和常量左值引用。但我觉得应该有更好的办法。
有没有一种明显的方法来通知编译器,尽管为了实现完美的转发,它是一个模板变量V
,但它应该是对std::pair<T,U>
参数的某种引用?
STL中容器的常见实现是如何实现这一点的?或者他们只是超载?
1条答案
按热度按时间5m1hhzi41#
{..}
没有类型,因此不能在insert
中推导。您可以通过提供默认模板类型来解决此问题:
Demo