简体   繁体   English

用大括号括起来的初始化列表完美转发

[英]perfect forwarding with brace enclosed initialiser list

For personal education I am coding up a basic implementation of a hash table (although the below is probably relevant to any container that is holding types that can be list initialised) and want to use modern elements of c++ as best as I understand them - in particular in this case, perfect forwarding.对于个人教育,我正在编写 hash 表的基本实现(尽管下面可能与任何包含可以初始化列表的类型的容器相关)并希望尽我所知地使用 c++ 的现代元素 - 在特别是在这种情况下,完美转发。

In doing so I have found I can't figure out a particular case - writing an insert function that achieves perfect forwarding while taking a brace enclosed initialiser list.在这样做的过程中,我发现我无法找出一个特定的情况——编写一个插入 function 以实现完美转发,同时采用括号括起来的初始化程序列表。 Failing to write this prevents using perfect forwarding when trying to emulate the std::unordered_map like insertion style container.insert({key,value}) .未能编写此内容会阻止在尝试模拟std::unordered_map (如插入样式container.insert({key,value})时使用完美转发。

To be specific, I have some hash table class which stores keys and values as std::pair<T,U> objects in (for example) lists at buckets stored in a vector (for a hash+chaining approach)具体来说,我有一些 hash 表 class 将键和值作为std::pair<T,U>对象存储在(例如)存储在向量中的桶中的列表中(对于哈希+链接方法)

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
    }
};

I then test my container by inserting with both lvalues and rvalues through calls such as然后我通过调用插入左值和右值来测试我的容器,例如

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

Examples 1 and 2 compile and work fine, but example 3 does not with compiler error (for example using the default type for the third template argument func - but the error is analgous for user provided hashes)示例 1 和 2 编译并正常工作,但示例 3 没有编译器错误(例如,对第三个模板参数func使用默认类型 - 但错误与用户提供的哈希类似)

error: no matching function for call to ‘HashTableLinearProbe<int, std::__cxx11::basic_string<char> >::insert(<brace-enclosed initializer list>)’

which seems reasonable - it can't figure out how to interpret what type of object the initialisation list is supposed to construct.这似乎是合理的 - 它无法弄清楚如何解释初始化列表应该构造的 object 类型。

An easy "solution" is to forget perfect forwarding and just overload the insert function to accept a right-hand reference and a const regular reference to a std::pair<T,U> .一个简单的“解决方案”是忘记完美转发并重载insert function 以接受右手引用和std::pair<T,U>的 const 常规引用。 But it feels like there should be a better way.但感觉应该有更好的方法。

Is there an obvious way to inform the compiler that, despite being a template variable V in order to achieve perfect forwarding, it should be some kind of reference to a std::pair<T,U> argument?是否有一种明显的方法可以通知编译器,尽管是模板变量V以实现完美转发,但它应该是std::pair<T,U>参数的某种引用?

How do common implementations of containers in STL achieve this? STL中容器的常见实现是如何实现的? Or do they just overload?还是他们只是超载?

{..} has not type, and so cannot be deduced in insert . {..}没有类型,因此不能在insert中推导出来。

You might work around that by providing default template type:您可以通过提供默认模板类型来解决这个问题:

template<typename V = std::pair<T, U>> // default to handle {..}
bool insert(V&& entry)
{
    ... = std::forward<V>(entry);
    // ..
    return true;
}

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM