问题标签 [forwarding-reference]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - lambda 中的完美转发?
使用一个函数,可以编写:
但是对于 lambda,我们没有T
:
如何在 lambda 中进行完美转发?decltype(x)
可以作为 in 的类型工作吗std::forward
?
c++ - 通用参考模板函数比非模板函数更可行的匹配背后的基本原理?
给定一个模板成员函数(......模板化类中的模板化构造函数,碰巧)采用可变参数通用引用,以及另一个候选函数(复制构造函数,在我的例子中),GCC和clang都选择通用引用模板复制对象时的重载决议。由于两个完全不同的编译器行为相同,我会假设这确实是“正确的事情”。https://godbolt.org/g/mip3Fi
上
的示例代码。
因此,当复制时,有两个具有相同数量参数的可行候选函数,两者都具有完美匹配(在模板版本的引用折叠之后),其中一个是候选函数模板特化,另一个不是. 当然,其中调用一个是“显然需要”,而调用另一个则不是。
我对重载决策的理解是,在候选函数集合中,要选择最佳可行的候选者,如果等效可行的模板和非模板候选者竞争,则选择非模板候选者。那将是复制构造函数。
显然,编译器(可能是标准?)的想法不同。这个相当不明显的例外的理由是什么?
奖金问题:
如何防止这种情况发生,即如何告诉编译器我真的想在制作副本时调用复制构造函数?
诸如消除不良候选者之类的东西enable_if_t<!is_same<container<T> const& blahblah...> blah>
,并按预期复制工作,但是该方法并没有太大帮助,因为当您使用多个参数调用可变参数模板时,它将无法编译(这是它的原始目的!)。
编写一个有initializer_list
意识的函数可以解决这个问题,但这会将一个完美转发的 emplace 变成一个复制和移动,这也不是很好。
编辑:(
上述链接代码,根据要求)
c++ - 类模板实例化和通用引用
在这样的代码中:
此函数根据函数是否convert
存在并将一组参数发送到一个函数或另一个函数,并且可以使用传递的参数调用,保持完整(我猜)它们的确切传递类型,以及当它的返回类型为 时int
,不管引用或 const限定词。
我对那段代码有三个疑问。
(1)
declval
返回类型仍然是通用引用吗?例如,declval<T>()
, withT = int&
, 它的返回类型是int&&
(一个真正的 r 值引用),还是在传递给另一个调用时int & &&
再次推导出为int&
遵循通用引用的通常规则?我认为它没有(正如@101010 所指出的),但我不知道在这种情况下如何进行完美的重载测试。(2)是否需要重新指定可变参数模板才能使用通用引用推导规则,或者由于(3)中已经推导出了正确的类型,所以它们保持推导的类型不变?
或者我可以写吗
?
模板类是一个实现细节,因此call_t
,它只会在内部实例化test
。
c++ - 转发模板参数的常量,我应该使用转发引用吗?
我想编写一个foo
应该调用operator()
其参数的函数,如下面的(损坏的)代码所示:
显然代码不起作用,因为operator()
是 non- const
,但foo()
需要它的参数是const
。
作为一个模板函数,foo()
应该const
与非仿函数一起使用const
,并且不要对其参数的 -ness 挑剔const
。
如果我foo()
通过删除const
以下内容进行更改:
...它也不起作用,因为您无法将右值引用转换为非const
左值引用,因此foo(MyFunctor{})
无法调用。
更改foo()
为转发参考可以解决所有问题:
但这是“正确”的方式吗?转发引用不应该只用于std::forward()
(即除了将其转发到另一个函数之外,不应触及参数)吗?
c++ - 类模板的模板参数推导的陷阱
我在这里阅读了关于类模板的模板参数推导的论文http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html。这个特性在 C++17 标准中,有些事情让我很困惑。
给定上面的代码,如果有人试图像这样实例化上面模板的一个实例
将始终调用右值引用重载吗?由于考虑扣除的过载集是
- 第二个重载永远不会优于第一个(因为现在是转发引用重载,而不是右值引用重载),那么这里应该发生什么?
- 如果没有明确指定参数,似乎永远无法调用最后一个
T
,这是预期的行为吗? - 在对类模板使用模板参数推导时,是否还有其他任何问题或样式指南需要牢记?
- 此外,用户定义的扣除指南是否需要在类定义之后?例如,您可以在类定义本身的类构造函数声明中使用尾随返回类型吗?(不像这里的迭代器构造函数http://en.cppreference.com/w/cpp/language/class_template_deduction)
c++ - 在 C++ 中转发引用和转换构造函数
假设我想创建一个函数,它通过引用同时接受左值和右值字符串参数,将它们转换为大写,并将它们打印到标准输出:
这可以正常工作,如下所示:
但是,为避免冗余,我想改用转发引用:
不幸的是,我不能upper_print
用字符串文字参数调用:
我知道将参数限制为std::string
对象的可能性,例如,通过使用std::enable_if
or static_assert
。但这在这里没有帮助。
从这个意义上说,是否有任何选项可以结合转发引用和转换构造函数的功能?
c++ - 具有右值引用而不是使用可变参数模板转发引用
我有一个结构X
和一个函数foo
,它们必须接收X
.
起初我只从一个论点开始,而且很简单(哦……更简单的时代):
但是后来我想扩展并接受可变数量的X
参数(仍然只有右值引用)。
但有一个问题。
- 第一个你不能拥有
auto foo(X&&... args)
这本来是理想的 - 第二现在你被迫这样做,
template <class... Args> auto foo(Args&&... args)
但现在你最终得到了转发引用,它会很高兴地接受非临时的:
为什么他们使用这种语法和规则来转发引用让我从乞求开始就感到困惑。这是一个问题。这种语法的另一个问题T&&
是X<T>&&
完全不同的野兽。但我们在这里偏离了轨道。
我知道如何使用或使用这两种解决方案来解决这个问题,static_assert
或者SFINAE
这两种解决方案都会使事情变得有点复杂,而且在我看来,如果语言设计得当,就永远不需要。甚至不要让我开始std::initializer_list
……我们又偏离了轨道。
所以我的问题是:是否有一个我被女巫遗漏的简单解决方案/技巧Args&&
/args
被视为右值引用?
就在我结束这个问题时,我认为我有一个解决方案。
为左值引用添加已删除的重载:
简单,优雅,应该可以,让我们测试一下:
好的,是的,我有它!
c++ - 将文字作为 const ref 参数传递
想象一下下面的简化代码:
(1) 抛开优化不谈,当 42 被传递给 时会发生什么foo
?
编译器是否将 42 粘贴在某处(在堆栈上?)并将其地址传递给foo
?
(1a) 标准中是否有任何规定在这种情况下要做什么(或者它是否严格取决于编译器)?
现在,想象一下稍微不同的代码:
它不会链接,除非我定义int bar::baz;
(由于 ODR?)。
(2) 除了 ODR,为什么编译器不能做上面 42 所做的事情?
简化事情的一个明显方法是定义foo
为:
但是,如果是模板,该怎么办?例如:
(3) 有没有一种优雅的方式来告诉foo
接受x
原始类型的值?还是我需要用 SFINAE 或类似的东西专门化它?
编辑:修改了内部发生foo
的事情,因为它与这个问题无关。
c++ - C++ 转发引用和右值引用
我了解转发引用是“对 cv 不合格模板参数的右值引用”,例如
这意味着上述函数可以同时采用左值和右值参考。
有些东西我不明白,例如
在上面的代码中,T&& 和 U&& 都是转发引用吗?
我写了一些代码来测试(VS2015编译器):
我期待那个 test.test1(a); 和 test.test2(a) 如果它们正在转发引用,它们都应该编译,但两者都没有。
有人可以向我解释一下吗?谢谢!
编辑 --------------谢谢,伙计们------------理查德和阿尔特米是正确的。
c++11 - 通用引用和命名参数理念
我写了这段代码并用 gcc 编译。我希望得到结果“2”,但结果是“0”。
其他编译器 clang 和 vc 打印“2”。它是未定义的行为吗?
cf 在http://rextester.com上构建 reslut