我读过很少关于&&的论文,我只是好奇,如果有:
void fnc_1(int&& p)
{
//...
}
void fnc(int&& r)
{
fnc_1(r);//am I suppose to/should I? call it like so:fnc_1(std::forward(r))
}
Run Code Online (Sandbox Code Playgroud)
或只是传递'r'就足够了?
template <typename T> void f(T&) {}
template <typename T> void f(T&&) {}
int main()
{
int x;
f(x); //ambiguous
}
Run Code Online (Sandbox Code Playgroud)
为什么这个电话不明确?第一个模板特化是f <int>(int&),第二个是f <int&>(int&).由于参数相同,因此根据偏序规则更加特殊的函数模板更好.然后根据标准14.8.2.4/9
如果对于给定类型,推导在两个方向上都成功(即,在上面的转换之后类型是相同的)并且P和A都是引用类型(在被上面提到的类型替换之前):
- 如果类型来自参数模板是一个左值引用,而参数模板中的类型不是,参数类型被认为比另一个更专业; ...
第一个模板有T&,第二个模板有T &&,所以第一个应该更专业.这有什么不对?
编辑:此代码在g ++ 4.6.1和VC++ 2010 Express中测试,两者都给出了模糊错误.
书中说:因为引用不是对象,我们可能没有定义对引用的引用.
int ival = 1024;
int &refVal = ival;
refVal = 2;
int ii = refVal;
int &refVal3 = refVal; // isn't this a definition of ref to ref?
int i = refVal;
int &refVal4 = 10;
double dval = 3.14;
int &refVal5 = dval;
Run Code Online (Sandbox Code Playgroud)
但是,该行不是错误,因为refVal3说它只是refVal的另一个别名,而refVal只是ival的另一个名称(refVal3绑定到refVal绑定到的对象,即ival)...所以refVal和refVal3都引用了ival的初始化器.
这是完全合理的,但如果这不是对引用的引用的定义,那么当它提到"因为引用不是对象时,我们可能没有定义对引用的引用"这本书究竟是什么意思.??
有人可以举个例子吗?
在回答这个问题时,我编写了这个工作代码,包装函数在模板参数中传递:
template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args... args)->decltype(fn(args...)){
return fn(args...);
}
#define WRAPPER(FUNC) wrapper<decltype(&FUNC), &FUNC>
Run Code Online (Sandbox Code Playgroud)
用法示例(我使用此代码进行测试):
int min(int a, int b){
return (a<b)?a:b;
}
#include<iostream>
using std::cout;
int main(){
cout<<WRAPPER(min)(10, 20)<<'\n';
}
Run Code Online (Sandbox Code Playgroud)
两个人告诉我使用完美转发.当我问到如何做到这一点时,其中一个人将我重定向到这里.我读了问题,仔细阅读了最佳答案,并改为wrapper:
#include<utility>
template<typename Fn, Fn fn, typename... Args>
auto wrapper(Args&&... args)->decltype(fn(std::forward<Args...>(args...))){
return fn(std::forward<Args...>(args...));
}
Run Code Online (Sandbox Code Playgroud)
它编译,除非我尝试使用上面的示例代码检查它.我该如何修复代码?
我有这个代码:
void f2(int& lvalue)
{
std::cout <<"lvalue\n";
}
void f2(int&& rvalue)
{
std::cout << "rvalue\n";
}
template<typename T>
void f(T&& param)
{
f2(param);
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话给f,我希望得到"左值" :
int v = 10;
f(v);
Run Code Online (Sandbox Code Playgroud)
并且如果我用以下方式调用f,则期望"rvalue" :
f(10);
Run Code Online (Sandbox Code Playgroud)
但是,我总是得到左值的情况.拜托,任何人都可以解释我错在哪里.
我有很多代码以某种方式执行完全相同的操作(继承的代码),并且我希望在重新编写代码时压缩代码而不会丢失功能.例如,让我们看看以下函数:
fnc(largetype & a, largetype & b) { f(A); f(B); };
fnc(largetype && a, largetype & b) { f(A); f(B); };
fnc(largetype & a, largetype && b) { f(A); f(B); };
fnc(largetype && a, largetype && b) { f(A); f(B); };
Run Code Online (Sandbox Code Playgroud)
所有这些都做了完全相同的事情,但参数可以是rvalues或lvalues而不会破坏函数逻辑.我希望允许用户传递任何适合问题的内容,但我也不想一块一块地复制粘贴所有代码.我可以这样做:
fnc(largetype & a, largetype & b) { f(A); f(B); };
fnc(largetype && a, largetype & b) { fnc(a,b) };
fnc(largetype & a, largetype && b) { fnc(a,b) };
fnc(largetype && a, largetype && b) { fnc(a,b) };
Run Code Online (Sandbox Code Playgroud)
这在技术上是正确的,尤其是内联,但对我来说似乎不对.有没有其他更好的方法来实现这样的效果? …
考虑以下功能:
template <class T>
constexpr /* something */ f(T&& x) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
并且假设我想根据传递给被调用函数的转发参数的类型来做sfinae myfunction.实现这一目标的一种方法是:
template <class T>
constexpr auto f(T&& x) -> decltype(myfunction(std::forward<T>(x))) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
而不是这样做,有没有办法在模板级别执行此操作:
// This code won't compile
template <class T, class R = decltype(myfunction(std::forward<T>(x)))>
constexpr R f(T&& x) {
// do something
}
Run Code Online (Sandbox Code Playgroud)
除了我还没有访问权限,x所以这段代码不会编译.有没有办法只基于T(可能使用std::declval)来实现这一目标?
注意:这不是一个X/Y问题,它只是一个例子来说明这种情况发生的地方:我不知道如何在不访问变量的情况下进行转发SFINAE,因为对我而言,行为std::forward仍然有点神秘.
c++ template-meta-programming perfect-forwarding trailing-return-type c++14
嗨,我std::optional在这里看一下这里的一个实现,我发现这段代码片段让我困惑:
// workaround: std utility functions aren't constexpr yet
template <class T> inline constexpr T&& constexpr_forward(typename
std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
Run Code Online (Sandbox Code Playgroud)
所以我不会通过以下方式理解这一点:
typename在这里做?只是声明以下部分是一种类型?std::remove_reference这里?我们没有在type&部件中添加参考吗?static_cast.template <class... Args>
constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {},那么它对args做了什么?非常感谢.
我遇到一个问题,gcc编译器将局部变量(非临时)作为函数的rvalue参数移动.我有一个简单的例子:
class A
{
public:
A() {}
A& operator=(const A&) { std::cout << "const A&\n"; return *this; }
A& operator=(A&&) { std::cout << "A&&\n"; return *this; }
};
class B
{
public:
B() {}
B& operator=(const B&) { std::cout << "const B&\n"; return *this; }
B& operator=(B&&) { std::cout << "B&&\n"; return *this; }
template<class T> B& operator=(const T&) { std::cout << "const T& (T is " << typeid(T).name() << ")\n"; return *this; }
template<class T> B& operator=(T&&) { std::cout …Run Code Online (Sandbox Code Playgroud) c++ templates lvalue-to-rvalue move-assignment-operator c++14
在C++中,似乎参数通常可以...直接在参数包名称之后扩展。例如,
template <class... Tys>
void function(Tys... params) {
function(params...);
}
Run Code Online (Sandbox Code Playgroud)
然而,当使用 时std::forward,...看起来似乎在参数包名称后面。例如,
template <class... Tys>
void function(Tys... params) {
function(std::forward<Tys>(params)...); // The '...' is outside the parenthesis of 'params'
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么会有差异?为什么下面的代码不正确?
template<class... Tys>
void function(Tys... params) {
function(std::forward<Tys>(params...));
}
Run Code Online (Sandbox Code Playgroud)
参数包在什么时候展开?我可能不完全理解它是如何std::forward工作的或者它如何完美地转发论点。
我很感激任何答案!
c++ templates variadic-functions variadic-templates perfect-forwarding