为什么要使用“通用参考文献”具有与右值引用相同的语法? [英] Why "universal references" have the same syntax as rvalue references?

查看:119
本文介绍了为什么要使用“通用参考文献”具有与右值引用相同的语法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚对这些(相当多的)新功能进行了研究,我想知道为什么C ++委员会决定为它们引入相同的语法?似乎开发人员没有必要浪费一些时间来了解其工作原理,而一种解决方案则可以考虑其他问题。就我而言,它是从可以简化为以下问题的问题开始的:

I just made some research about those (quite) new features and I wonder why C++ Committee decided to introduce the same syntax for both of them? It seems that developers unnecessary have to waste some time to understand how it works, and one solution lets to think about further problems. In my case it started from problem which can be simplified to this:

#include <iostream>

template <typename T>
void f(T& a)
{
    std::cout << "f(T& a) for lvalues\n";
}

template <typename T>
void f(T&& a)
{
    std::cout << "f(T&& a) for rvalues\n";
}

int main()
{
    int a;
    f(a);
    f(int());

    return 0;
}

我首先在VS2013上对其进行了编译,并按预期运行,结果:

I compiled it firstly on VS2013 and it worked as I expected, with this results:

f(T& a) for lvalues
f(T&& a) for rvalues

但是有一个可疑的事情:intellisense在f(a)下划线。我进行了一些研究,我理解这是因为类型崩溃(Scott Meyers命名为通用引用),所以我想知道g ++对它的看法。当然没有编译。 Microsoft非常高兴地实现了其编译器以更直观的方式工作,但是我不确定它是否符合标准,并且IDE是否应存在这种差异(编译器与intellisense,但实际上可能从某种意义上来说)。好,回到问题所在。我是这样解决的:

But there was one suspicious thing: intellisense underlined f(a). I made some research and I understood that it is because type collapsing (universal references as Scott Meyers named it), so I wondered what g++ thinks about it. Of course it didn't compiled. It is very nice that Microsoft implemented their compiler to work in more intuitive way, but I'm not sure if it is according to the standard and if there should be this kind of difference in IDE (compiler vs intellisense, but in fact there may be some sense in it). Ok, return to the problem. I solved it in this way:

template <typename T>
void f(T& a)
{
    std::cout << "f(T& a) for lvalues\n";
}

template <typename T>
void f(const T&& a)
{
    std::cout << "f(T&& a) for rvalues\n";
}

现在没有任何类型的崩溃,只是(r / l)值。它在g ++上编译,intellisense不再抱怨,我几乎感到满意。差不多,因为我考虑过如果要更改右值引用传递的对象状态下的内容,该怎么办?我可以在必要时描述一些情况,但是此描述太长,无法在此处进行介绍。我是这样解决的:

Now there wasn't any type collapsing, just normal overloading for (r/l)values. It compiled on g++, intellisense stopped complaining and I was almost satisfied. Almost, because I thought about what if I will want to change something in object's state which is passed by rvalue reference? I could describe some situation when it could be necessary, but this description is too long to present it here. I solved it in this way:

template <typename T>
void f(T&& a, std::true_type)
{
    std::cout << "f(T&& a) for rvalues\n";
}

template <typename T>
void f(T&& a, std::false_type)
{
    std::cout << "f(T&& a) for lvalues\n";
}

template <typename T>
void f(T&& a)
{
    f(std::forward<T>(a), std::is_rvalue_reference<T&&>());
}

现在它可以在所有经过测试的编译器上进行编译,并且可以让我在其中更改对象状态右值引用实现,但是看起来不太好,这是因为通用引用和右值引用的语法相同。所以我的问题是:为什么C ++委员会没有为通用引用引入另一种语法?我认为该功能应该通过T?,auto?或类似的方式发出信号,而不是T&&。和自动&&只是与右值引用冲突。使用这种方法,不仅对于MS编译器,我的第一个实现都是完全正确的。谁能解释委员会的决定?

Now it compiles on all tested compilers and it lets me to change object state in rvalue reference implementation, but it doesn't looks very nice, and this is because of the same syntax for universal references and rvalue references. So my question is: Why C++ Committee didn't introduce some another syntax for universal references? I think that this feature should be signalized, for example, by T?, auto?, or something similar, but not as T&& and auto&& which just collide with rvalue references. Using this approach my first implementation would be perfectly correct, not only for MS compiler. Can anyone explain Committee decision?

推荐答案

我认为这是相反的事情。最初的想法是在语言中引入右值引用,这意味着提供双与号引用的代码并不关心所引用的对象会发生什么。这允许移动语义。很好。

I think it happened the other way around. The initial idea was to introduce rvalue-references into the language, meaning that "the code providing the double-ampersand reference does not care about what will happen to the referred-to object". This permits move semantics. This is nice.

现在。该标准禁止构造对引用的引用,但这始终是可能的。考虑:

Now. The standard forbids constructing a reference to a reference, but this was always possible. Consider:

template<typename T>
void my_func(T, T&) { /* ... */ }

// ...

my_func<int&>(a, b);

在这种情况下,第二个参数的类型应为 int& & ,但这在标准中明确禁止。因此,即使在C ++ 98中,引用也必须折叠。在C ++ 98中,引用只有一种,因此折叠规则很简单:

In this case the type of the second parameter should be int & &, but this is explicitly forbidden in the standard. So the references have to be collapsed, even in C++98. In C++98, there was only one kind of reference, so the collapsing rule was simple:

& & -> &

现在,我们有两种引用,其中& 表示我不在乎对象可能发生什么,而& 表示我可能在乎对象可能发生什么 ,因此您最好注意自己在做什么。考虑到这一点,折叠规则自然会流动:只有在没有人关心对象发生什么变化的情况下,C ++才应该将引用折叠到&&

Now, we have two kinds of references, where && means "I don't care about what may happen to the object", and & meaning "I may care about what may happen to the object, so you better watch what you're doing". With this in mind, the collapsing rules flow naturally: C++ should collapse referecnces to && only if no one cares about what happens to the object:

& & -> &
& && -> &
&& & -> &
&& && -> &&

有了这些规则,我想是Scott Meyers注意到了这部分规则:

With these rules in place, I think it's Scott Meyers who noticed that this subset of rules:

& && -> &
&& && -> &&

表明&& 是正确的-关于引用折叠的中性,并且在发生类型推导时, T& 构造可用于匹配任何类型的引用,并创造了术语通用参考。这不是委员会发明的。

Shows that && is right-neutral with regards to reference collapsing, and, when type deduction occurs, the T&& construct can be used to match any type of reference, and coined the term "Universal reference" for these references. It is not something that has been invented by the Committee. It is only a side-effect of other rules, not a Committee design.

因此,在没有类型推导的情况下,引入该术语是为了区分实数右值引用。出现,保证被& ,以及那些类型推断的UNIVERSAL引用,不能保证保持& 在模板专门化时间。

And the term has therefore been introduced to distinguish between REAL rvalue-references, when no type deduction occurs, which are guaranteed to be &&, and those type-deduced UNIVERSAL references, which are not guaranteed to remain && at template specialization time.

这篇关于为什么要使用“通用参考文献”具有与右值引用相同的语法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆