Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 完美转发对象的成员_C++_C++11_Rvalue Reference_Perfect Forwarding - Fatal编程技术网

C++ 完美转发对象的成员

C++ 完美转发对象的成员,c++,c++11,rvalue-reference,perfect-forwarding,C++,C++11,Rvalue Reference,Perfect Forwarding,假设我有两个structs: struct X {}; struct Y { X x; } 我有以下职能: void f(X&); void f(X&&); 我如何编写一个函数g(),分别将Y&或Y&完美地转发到X&或X&到f(): template <typename T> void g(T&& t) { if (is_lvalue_reference<T>::value) { f(t.x); } else {

假设我有两个
struct
s:

struct X {};
struct Y { X x; }
我有以下职能:

void f(X&);
void f(X&&);
我如何编写一个函数
g()
,分别将
Y&
Y&
完美地转发到
X&
X&
f()

template <typename T>
void g(T&& t) {
  if (is_lvalue_reference<T>::value) {
    f(t.x);
  } else {
    f(move(t.x));
  }
}
模板
无效g(T&T){
if(is_lvalue_reference::value){
f(t.x);
}否则{
f(move(t.x));
}
}

上面的代码说明了我的意图,但随着参数数量的增加,它的可伸缩性不是很强。有没有一种方法可以让它实现完美的转发并使其具有可扩展性?

我认为这会奏效,尽管我不确定:

template<class T, class M>
struct mforward {
  using type = M&&; 
};
template<class T, class M>
struct mforward<T&, M> {
  using type = M&; 
};

template <typename T>
void g(T&& t) {
  f(std::forward<typename mforward<T, decltype(t.x)>::type>(t.x));
}
模板
结构向前{
使用type=M&;
};
模板
结构向前{
使用type=M&;
};
模板
无效g(T&T){
f(标准:正向(t.x));
}
模板
无效g(T&T){
f(std::forward(t.x);
}

我认为将
is_lvalue_reference::value
更改为
is_lvalue_reference::value
将具有您想要的语义,但我认为您想要的语义是有问题的…(对于拙劣的答案,我感到抱歉)。我认为它无法扩展的原因是因为设计一开始就有问题。“移动”子对象意味着什么?这将在什么状态下离开主对象?即使有一个简单的方法来编写,它看起来像是结构糟糕的代码…+1我必须用libc++解决几乎完全相同的问题。我提出的解决方案看起来与Pubby的非常相似。我不仅想将
T
的l/r值“应用”到
M
,还想将
T
的cv资格应用到
M
。我找到了数据成员以外的应用程序。出于好奇,我把它称为
\uu apply\u cv
,它是开源代码:@Howard请参阅我的答案以获取替代方案。还是我错过了什么?还有@Howard谈论简历资格让我想到了这个答案的一个缺陷
decltype(t.x)
仅提供声明的
x
类型。如果
T
const
,但是
x
被声明为
inta
,那么您的转发将尝试将内容转发为
int&
/
int&
。您需要说一些类似于
typename remove\u reference::type
的话来考虑
t
的常量。这也考虑了
mutable
成员,但我不知道move在哲学上对一个
const
对象的可变成员意味着什么。@Johannes:我同意,你的解决方案更适合这个用例。@Howard:如果Johannes的解决方案不起作用,情况会是什么样子,但是
\u apply\u cv
一个人会@Pubby,因为
rvalue.foo
是一个rvalue。我能想到为什么它可能是有意义的(如果容器的生命周期很短并且是一个右值,那么所包含的对象也共享该属性),但我不熟悉其原理,也不知道其原理,所以我不能对此说任何话。
rvalue.foo
应该是一个xvalue属性。@curi一些委员会成员这样说。但是,他会怎么解释“rvalue”(对象表达式)有时保持为prvalue的原因呢?反对将成员选择设置为xvalue是因为它的动态类型不能与表达式的静态类型不同。这正是我要寻找的答案。真是个天才!!
template <typename T>
void g(T&& t) {
  f(std::forward<T>(t).x);
}