C++ 完美转发困境

C++ 完美转发困境,c++,c++11,C++,C++11,假设我有这个结构: template <typename ...A> struct A { void f(A&& ...args) { fwd(std::forward<A>(args)...); } template <typename ...B> void g(B&& ...args) { fwd(std::forward<B>(args)...); } }; 模板

假设我有这个结构:

template <typename ...A>
struct A
{
  void f(A&& ...args)
  {
    fwd(std::forward<A>(args)...);
  }

  template <typename ...B>
  void g(B&& ...args)
  {
    fwd(std::forward<B>(args)...);
  }
};
模板
结构A
{
无效f(A&&…参数)
{
前进档(标准:前进档(参数)…);
}
模板
无效g(B&…参数)
{
前进档(标准:前进档(参数)…);
}
};
如果
A..=B.
?依我看,他们应该这样做,但我只是想确定一下

编辑: 这个问题的原因是关于转发函数应该如何始终是模板函数的常见讲座。显然,对于
f
,情况并非如此

如果
A..=B.


对。我看不出有什么理由他们不应该这样做。

是的,如果
A..=B.
,行为上没有区别。但是,关于转发函数需要模板化的常见建议的原因是,您宁愿让编译器推断类型(如函数模板),而不必指定正确的类型(如类模板)。以下类型
X
(当然,它们不满足
a..==B..
)的代码片段说明了这种差异:

X;
A::f(X());
A::g(X())//这里,f和g具有相同的行为
A::f(x)//未能编译,因为A::f需要右值引用。
A::g(x)//按预期工作-这里,B..=X&,而A..=十,。
A::f(X())//哦,不!fwd得到一个常量X&。
A::g(X())//正确转发为B..=十、 尽管常数X&。

这取决于您所说的它们是否都能完美地向前移动
f()
只接受右值引用作为参数,并将它们作为右值转发到
fwd()
g()
接受左值和右值引用,并在维护各自的值类别的同时转发它们。@Praetorian:为什么只接受右值引用?我们不知道使用了
A
的什么实例化。比如,
A
A
Aint const&>
A
…您所说的是因为演绎规则而发生的,如果您显式实例化会怎么样?也就是说,您可以使用引用类型参数实例化
A
。@Deduplicator Good point,没有想到这些情况。即便如此,
f()
的参数的左值或右值是固定的,如果
A..=B.
,正如我在问题中所写的。正如您在上面的评论中所看到的,有时会出现一些混乱。
X x;
A<X>::f(X());
A<X>::g(X());//here, f and g have the same behaviour

A<X>::f(x);//fails to compile, since A<X>::f expects an rvalue ref.
A<X>::g(x);//works as expected - Here, B... = X&, while A... = X.

A<const X&>::f(X());//oh noes! fwd gets a const X&.
A<const X&>::g(X());//forwards correctly as B... = X, even though A... = const X&.