为什么auto &&不是右值参考?
Widget&& var1 = Widget(); // rvalue reference
auto&& var2 = var1; //var2 not rvalue reference
Run Code Online (Sandbox Code Playgroud)
下面是右值参考示例
void f(Widget&& param); // rvalue reference
Widget&& var1 = Widget(); // rvalue reference
Run Code Online (Sandbox Code Playgroud)
为什么var2不是右值参考,而f和var2是右值参考?
使用Efficient Modern C++,第25项.我们有一个例子
class Widget {
public:
template<typename T>
void setName(T&& newName)
{ name = std::forward<T>(newName); }
...
};
Run Code Online (Sandbox Code Playgroud)
class Widget {
public:
void setName(const std::string& newName)
{ name = newName; }
void setName(std::string&& newName)
{ name = std::move(newName); }
...
};
Run Code Online (Sandbox Code Playgroud)
Widget w;
w.setName("Adela Novak");
Run Code Online (Sandbox Code Playgroud)
现在假设情况1,该书指出文字被传递给w的名称数据成员中的t std :: string的赋值运算符.
假设情况2,本书指出 - >首先从文字创建临时,调用字符串构造函数,因此setName参数可以绑定到它,并且将此临时文件移动到w的名称数据成员中.
为什么这种行为上的差异会产生,我该怎么想呢?
也就是说,为什么在案例1中不需要临时的?为什么会有区别?T &&是否被推断为对字符串的右值引用,因此得出与案例2相同的行为(显然不是,根据本书,但为什么)?
考虑我们需要实现一个f带有模板参数的函数T t。该函数不应同时复制t和接受rvalues和lvalues,因此可能有两种实现:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
Run Code Online (Sandbox Code Playgroud)
如果我们想改变t里面f的值或者需要保留类的值,就得使用第二个版本了。那么根据这个思路,我们何时以及为什么会选择第一个选项?
我有一个问题将const ref参数传递给调用其他函数的模板函数.请考虑以下代码:
struct A
{
void foo(const int& i) { }
};
template <class ...Args>
void a_caller(A& a, void(A::*f)(Args...), Args&& ...args)
{
(a.*f)(std::forward<Args>(args)...);
}
int main()
{
int i = 42;
A a;
a_caller(a, &A::foo, i); // (1) compiler error
a_caller<const int&>(a, &A::foo, i); // (2) ok
}
Run Code Online (Sandbox Code Playgroud)
所以,我有一个成员函数A::foo与const int&我想在包装器中调用的参数a_caller.第(1)行导致以下错误:
'void a_caller(A &,void (__thiscall A::* )(Args...),Args &&...)' : template parameter 'Args' is ambiguous
see declaration of 'a_caller'
could be 'const int&'
or 'int&'
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是为什么会这样?我给编译器一个非重载函数A …
在思考如何解决std::min 悬空引用问题时,我想到的是为要删除的rvalues添加一个重载(实际上是3 - 对于每个组合).问题是T&&转发引用,而不是右值引用.
我想将此问题与std::min具体问题分开,并使其更加通用.这std::min可以作为一个例子,为什么你需要这样的东西.
让我们简化并概括问题:
// this has the same problem as `std::min`: if t binds to a temporary,
// and the result is assigned to `auto&`, the result is a dangled reference
template <class T>
const T& foo(const T& t)
{
return t;
}
// incorrect attempt to prevent foo from being called with a temporary argument
// `T&&` is a forwarding reference, not an rvalue reference
template <class T> …Run Code Online (Sandbox Code Playgroud) 我想要一个这样的函数:
template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {
}
Run Code Online (Sandbox Code Playgroud)
参数是(在单词中因为C/C++类型语法是mental):
MyClass.MyClass采用unsigned int并返回T.这种工作,但如果我用一个l值引用作为第一个参数调用它我得到一个错误,如:
候选模板被忽略:推导出参数'C'的冲突类型('MyClass&'与'MyClass')
据我所知,它是C从第一个和第二个参数中推导出来的,但是会产生不同的推论并且会混淆.
根据这个答案你可以让它只对第一个参数进行推论,并以某种方式typename在第二个参数上使用关键字.但是当我希望它推导出参数(T)中的一种类型而不是其他类型()时,我无法弄清楚这样做的语法C.
这个答案也很有帮助,但是他们只是根本不使用引用来解决它C,在这种情况下它同样有效,但不是我的.
这可能吗?
据我所知,右值引用不能绑定到左值。例如,
\n\nvoid func(Foo &&f) {}\nint main() {\n Foo f;\n func(f);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编译器抱怨:\n 错误:无法将 \xe2\x80\x98Foo&&\xe2\x80\x99 类型的右值引用绑定到 \xe2\x80\x98Foo 类型的左值
\n\n但是,为什么右值引用类型的模板参数可以绑定到左值?\ne.g.
\n\ntemplate <typename T> void funcTemp(T &&arg) {}\nint main() {\n Foo f;\n funcTemp(f);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编译器不会报告该错误。\n为什么?
\n我有一个结构X和一个foo必须接收rvalue引用的函数X.
起初我只用一个参数开始,这很简单(哦......更简单的时间):
auto foo(X&& arg) -> void {...};
X x;
foo(x); // compile error [OK]
foo(std::move(x)); // accepted [OK]
foo(X{}); // accepted [OK]
Run Code Online (Sandbox Code Playgroud)
但后来我想扩展并接受可变数量的X参数(仍然只是rvalue rferences).
但有一个问题.
auto foo(X&&... args)理想的template <class... Args> auto foo(Args&&... args)但现在你最终得到转发参考,这将很乐意接受非临时性的:template <class... Args>
auto foo(Args&&... args) -> void { ... };
X x1, x2;
foo(x1, x2); // accepted [NOT OK]
foo(std::move(x1), std::move(x2)); // accepted [OK]
foo(X{}, X{}); // accepted [OK]
Run Code Online (Sandbox Code Playgroud)
为什么他们使用这种语法和规则来转发引用因为乞讨而困惑我.这是一个问题.这种语法的另一个问题是,T&&并且 …
c++ rvalue-reference variadic-templates c++14 forwarding-reference
我有一个函数foo通过引用获取参数,我希望它在rvalue和左值引用上采取不同的行为.(它不会改变引用的值,我可以添加)我知道如果我写:
template <typename T> foo(T&& x);
Run Code Online (Sandbox Code Playgroud)
我已经声明了转发引用,而不是rvalue引用,这意味着:
template <typename T> foo(const T& x);
template <typename T> foo(T&& x);
Run Code Online (Sandbox Code Playgroud)
可能不会得到我想要的东西.
所以,我的问题是:影响两种引用之间不同行为的正确方法是什么?
返回前向(通用)引用的最自然方式是什么?
struct B{
template<class Ar> friend
/* 1*/ Ar&& operator<<(Ar&& ar, A const& a){...; return std::forward<Archive>(ar);}
template<class Ar> friend
/*OR 2*/ Ar& operator<<(Ar&& ar, A const& a){...; return ar;}
template<class Ar> friend
/*OR 3*/ Ar operator<<(Ar&& ar, A const& a){...; return std::forward<Ar>(ar);}
template<class Ar> friend
/*OR 4*/ Ar operator<<(Ar&& ar, A const& a){...; return ar;}
/*OR 5*/ other??
}
Run Code Online (Sandbox Code Playgroud)
我想到的情况是一个类似流的对象,它被构造并立即使用.例如:
dosomethign( myarchive_type{} << B{} << B{} << other_unrelated_type{} );
Run Code Online (Sandbox Code Playgroud) #include <iostream>
class A
{
public:
A() {};
};
template <class T>
class Test
{
public:
void func1(T&& t)
{
}
};
int main()
{
A a;
Test<A> o1;
o1.func1(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时出现以下错误
error C2664: 'void Test<A>::func1(T &&)': cannot convert argument 1 from 'A' to 'T &&'
note: You cannot bind an lvalue to an rvalue reference
Run Code Online (Sandbox Code Playgroud)
o1是通过实例化模板类 Test 来获得的"A"。所以调用o1.func1(a)应该知道void func1(T&& t)应该解析为void func1(A&& t)
我认为T&&invoid func1(T&& t)应该被推导为通用引用或转发引用,因为它来自模板类型参数。那么为什么在上面的错误中会说呢 …
比较以下两种情况:
template<class... Args>
void f1(Args&&... args) { do_smth(std::forward<Args>(args)...); }
auto f2 = [](auto&&... args) { do_smth(std::forward<decltype(args)>(args)...); };
Run Code Online (Sandbox Code Playgroud)
std::forward传递或不传递的类型是否有任何差异?
根据我的理解,当您使用 , 指定转发引用时T&&,&&并不与传递的参数“匹配”,而是一种将“原始引用”信息“存储”到T(T将是&, const &,&&或const &&根据值类别传递的参数),然后将此类“原始引用”信息结合起来,使用通常的规则等&&计算最终的引用类型。& + && = &
我不知道的是,是否decltype(args)会解析为此类计算“之前”或“之后”的类型,或者结果类型是否与“原始引用”不同,因此指定的类型是否有任何差异std::forward在f1和f2.
注意:我不能使用 C++20,并且模板 lambda 不在问题范围内。
我看了这个约(令人难以置信的好写的)文章转发参考用C斯科特迈尔斯++ 11.
现在,重点关注本文的这一部分:
Run Code Online (Sandbox Code Playgroud)template <class... Args> void emplace_back(Args&&... args); // deduced parameter types ? type deduction; ... // && ? universal references
因此,与其他情况相比,省略号不会&&成为右值引用,但它仍然是通用引用.
根据我的理解,当我们有通用引用时,我们可以调用函数传递rvalue和lvalues(哇,太酷了!)
现在,我已经实现了这个功能:
template <typename ReturnType, typename... Args>
ReturnType callFunction(MemFunc<ReturnType, Args...> memFunc, Args&& ... args) { ...
Run Code Online (Sandbox Code Playgroud)
因此(使用与前一示例相同的逻辑)&&意味着转发引用.
但如果我试着打电话:
typedef vector<double> vecD;
vecD vec;
mem.callFunction<vecD, vecD>(sortFunc, vec);
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨 You cannot bind an lvalue to an rvalue reference
为什么会这样?
整个代码:
#include <functional>
#include <vector>
using namespace std;
struct MultiMemoizator { …Run Code Online (Sandbox Code Playgroud)