C++ 为什么';t`const int ci=2;标准:前进<;int>;(ci);`工作以及如何修复/解决它?

C++ 为什么';t`const int ci=2;标准:前进<;int>;(ci);`工作以及如何修复/解决它?,c++,c++11,perfect-forwarding,C++,C++11,Perfect Forwarding,简单的问题,为什么不起作用(意味着一份ci) #包括 int main(){ 常数int ci=2; 标准:转发(ci); } prog.cpp:在函数“int main()”中: prog.cpp:6:23:错误:调用“forward(const int&)”时没有匹配函数 这个问题在编写一些模板材料时表现出来,我有一个简单的holder类型,如下所示。为了避免不必要的拷贝,我尽可能使用完美转发,但这似乎是问题的根源 template<class T> struct holder

简单的问题,为什么不起作用(意味着一份
ci

#包括
int main(){
常数int ci=2;
标准:转发(ci);
}
prog.cpp:在函数“int main()”中:
prog.cpp:6:23:错误:调用“forward(const int&)”时没有匹配函数

这个问题在编写一些模板材料时表现出来,我有一个简单的holder类型,如下所示。为了避免不必要的拷贝,我尽可能使用完美转发,但这似乎是问题的根源

template<class T>
struct holder{
    T value;

    holder(T&& val)
        : value(std::forward<T>(val))
    {}
};

template<class T>
holder<T> hold(T&& val){
    // T will be deduced as int, because literal `5` is a prvalue
    // which can be bound to `int&&`
    return holder<T>(std::forward<T>(val));
}

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}

int main(){
    foo(hold(5));
}
模板
结构持有者{
T值;
支架(T&val)
:值(标准::正向(val))
{}
};
模板
持有人持有(T&val){
//T将被推断为int,因为文字'5'是一个pr值
//它可以绑定到'int'&&`
申报持有人(标准:远期(val));
}
模板
无效foo(持票人常数和高度)
{
std::tuple t;//人为的,实际函数需要更多参数
std::get(t)=std::forward(h.value);//h.value是`const t`
}
int main(){
foo(hold)(5);;
}
如果需要更多信息,请告诉我。
我们非常感谢任何绕过此问题的想法。

这:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}
它丢弃了
常量
。为了避免扔掉
常量
,您可以:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<const int>(ci);
}
在代码中:

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}
你的评论甚至仍然正确

这是一个枯燥的阅读,但调查什么是可以做的,什么是不能做的,以及为什么。这在标准化之前已被修改,但在最终N3143配方中,来自的用例和基本原理仍然有效且不变

您可以使用
转发
执行的操作:

  • 您可以将左值作为左值转发
  • 可以将左值作为右值转发
  • 您可以将右值作为右值转发
  • 可以将较少的cv限定表达式转发给更多的cv限定表达式
  • 可以将派生类型的表达式转发到可访问的、明确的基类型
使用
转发
可以不做的事情:

  • 不能将右值作为左值转发
  • 不能将更多cv限定表达式转发到更少cv限定表达式
  • 您不能转发任意类型转换(例如,将
    int
    转发为
    double

您应该这样做:
template-struct-holder{holder(T-val):value(std::move(val)){};模板持有者hold(T val){return holder(std::move(val));}
(是的,我知道它看起来很混乱。:)@GMan:但我不想删除引用:(然后称之为
hold(std::ref(x));
:P@GMan:Eww./似乎我需要解释我正在尝试做什么。我目前正在尝试实现位置参数,比如
void foo(param_pack p){…}/*…*/foo((_2=some_var,_1=1))
。这是一个虚构的例子,但应该能让我明白我的意图。遗憾的是,我遇到了一个又一个问题。:(现在是引用,当你试图移动它们时它会断开:哦,等等。我刚刚有了一个解决这个问题的好主意~Partial specializations ftw。感谢你给出了这个广泛的答案。有什么办法“保存”吗值的可转发性?正如我在对问题本身的评论中所说,我正在尝试实现位置参数,并且我希望转发所有参数,就像它们直接传递到函数中一样。是我目前拥有的完整代码(~300 LoC),即使GCC似乎不喜欢我在
开关上的SFINAE技巧。我已经在我的系统中发现了一些限制,例如,我无法将
t
类型的临时变量绑定到
t const&
t&
参数包中的
t&
,而不获得悬空引用。有没有办法修复/改进这个问题(如果你愿意涉猎代码)?@Xeo:我不确定。但我能够修复你的代码,使其在clang/libc++上运行。
std::move(pos::template switch(arg1,arg2,arg3)。value
(添加“template”3个位置)。使param_pack BoundList构造函数无需泛型:
template param_pack(bound_list&&bl)
。通过这些更改,您的代码为我运行并输出:
值ctor Move ctor Move ctor Move ctor Move ctor Move ctor Copy ctor Move ctor Move ctor hi 3 1 Dtor
D'oh,可怕的嵌套模板说明符!感谢您的修复。实际上,我链接的代码不是最新的,但我注意到太晚了。我已经对c进行了更改tor,因为绑定列表无论如何只会是临时的。VS11上的输出对我来说是一样的,但我想得到一份副本。遗憾的是,step into对VS11并没有真正的帮助,因为它发生的相关函数被深埋在宏中以模拟可变模板(对于任何阅读本文并感兴趣的人来说,这是GCC的固定代码。
#include <utility>

int main(){
  const int ci = 2;
  std::forward<const int>(ci);
}
Forward an lvalue `const int` as an rvalue `const int`.
template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}
    std::get<0>(t) = h.value; // h.value is `const T`