标签: perfect-forwarding

为什么要使用完美转发的值(仿函数)?

C++ 11(和C++ 14)引入了针对通用编程的其他语言结构和改进.这些功能包括:

  • R值参考
  • 参考折叠
  • 完美转发
  • 移动语义,可变参数模板等

我在浏览较早草案的的C++ 14规范(现在更新文本)和码中的示例中§20.5.1,编译时整数序列,我发现有趣和奇特.

template<class F, class Tuple, std::size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
  return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
}

template<class F, class Tuple>
decltype(auto) apply(F&& f, Tuple&& t) {
  using Indices = make_index_sequence<std::tuple_size<Tuple>::value>;
  return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), Indices());
}
Run Code Online (Sandbox Code Playgroud)

在线这里[intseq.general]/2.

  • 为什么功能fapply_impl被转发,即为什么std::forward<F>(f)(std::get...
  • 为什么不直接应用该功能f(std::get...

c++ perfect-forwarding c++11 c++14

32
推荐指数
2
解决办法
1521
查看次数

继承构造函数在C++中有用吗?

当我参加C++标准委员会会议时,他们正在讨论删除继承构造函数的优缺点,因为还没有编译器供应商实现它(用户没有要求它的意义).

让我快速提醒大家继承构造函数是什么:

struct B
{
   B(int);
};

struct D : B
{
  using B::B;
};
Run Code Online (Sandbox Code Playgroud)

一些供应商提出使用r值引用和可变参数模板(完美转发构造函数),在继承类中提供可以避免继承构造函数的转发构造函数是微不足道的.

例如:

struct D : B
{
  template<class ... Args> 
    D(Args&& ... args) : B(args...) { } 
};
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

1)您能否从编程经验中提供真实世界(非人为的)示例,这些示例将从继承构造函数中获益匪浅?

2)您是否有任何技术原因可以将"完美的转发建设者"排除在适当的替代方案之外?

谢谢!

c++ inheritance constructor perfect-forwarding c++11

31
推荐指数
1
解决办法
1627
查看次数

转发返回值.需要std :: forward吗?

我正在编写从其他库中包含很多功能和方法的库.为了避免复制返回值我正在这样应用std::forward:

template<class T>
T&& wrapper(T&& t) { 
   f(t);  // t passed as lvalue  
   return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)

f返回void并获取T&&(或超载值).包装器总是返回包装器的参数,返回值应该保留参数的值.我是不是真的需要使用std::forwardreturn?RVO会让它变得多余吗?它是参考(R或L)的事实是否是多余的?如果return不是最后一个函数语句(在some if中),是否需要它?

如果wrapper()应该返回void或者是有争议的T&&,因为调用者可以通过arg访问评估值(参考,R或L).但在我的情况下,我需要返回值,以便wrapper()可以在表达式中使用.

它可能与这个问题无关,但众所周知,函数f不会被窃取t,所以第一次使用std::forwardin f(std::forward<T>(t))是多余的,它被我删除了.

我写过小测试:https://gist.github.com/3910503

测试显示,返回未转发T- 确实在gcc48和clang32中创建了额外的副本与-O3(RVO没有启动).

此外,我无法从UB中获得不良行为:

auto&& tmp = wrapper(42); 
Run Code Online (Sandbox Code Playgroud)

它没有证明任何原因,因为它是未定义的行为(如果它是UB).

c++ return rvalue-reference perfect-forwarding c++11

31
推荐指数
2
解决办法
4737
查看次数

如何在一般的lambda中完美地转发`auto &&`?

C++ 14支持通用lambda.但是,clang 3.4拒绝以下代码.

#include <utility>

void f(int);
void f(int&);

int main()
{
    [](auto&& v) { f(std::forward<auto>(v)); }(8); // error
}
Run Code Online (Sandbox Code Playgroud)

如何auto&&在一般的lambda中完美前进?

c++ lambda perfect-forwarding auto c++11

30
推荐指数
1
解决办法
2879
查看次数

为什么在访问元素之前在容器上使用std :: forward?

Scott Meyers在他的新书"Effective Modern C++"中将以下函数显示为使用示例decltype(auto)(第28页):

template<typename Container, typename Index>
decltype(auto) 
authAndAccess(Container&& c, Index i)
{
  authenticateUser();
  return std::forward<Container>(c)[i];
}
Run Code Online (Sandbox Code Playgroud)

我的问题很简单.为什么我们需要std::forwardc这里申请?我们没有经过c任何地方,我们正在呼吁operator[]它.并且没有一个标准容器具有ref-qualified重载(r值/ l值重载)operator[].

所以我认为只有两个原因std::forward:

  1. 考虑实施ref-qualified重载的潜在容器operator[].
  2. 为了保持一致性:只要使用声明为转发(通用)引用的变量,就应用std::forward它.期.

还有其他原因吗?

c++ perfect-forwarding c++14

21
推荐指数
1
解决办法
394
查看次数

为什么不使用`make_x()`函数尽可能省略移动构造函数?

我无法弄清楚为什么在最后一种情况下启用了复制省略时调用移动构造函数(甚至是强制性的,例如在C++ 17中):

class X {
  public:
    X(int i) { std::clog << "converting\n"; }
    X(const X &) { std::clog << "copy\n"; }
    X(X &&) { std::clog << "move\n"; }
};

template <typename T>
X make_X(T&& arg) {
  return X(std::forward<T>(arg));
}

int main() {
  auto x1 = make_X(1);    // 1x converting ctor invoked
  auto x2 = X(X(1));      // 1x converting ctor invoked
  auto x3 = make_X(X(1)); // 1x converting and 1x move ctor invoked
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,哪些规则阻碍了移动构造函数被省略?

UPDATE

调用移动构造函数时可能更直接的情况: …

c++ language-lawyer move-semantics copy-elision perfect-forwarding

21
推荐指数
2
解决办法
1250
查看次数

在C++中重命名(别名/转发)函数的最佳方法是什么?

(我将这个问题限制在C++ 11中,因为我相信在C++ 98中没有通用的方法).

假设我有一组复杂的(在签名方面)模板函数和/或重载函数,我想以完全相同的方式使用这些函数,但使用不同的名称(即别名).

例如:

template<class A, class B, class C> 
D fun(A a, B& b, C&& c){ ... }

template<class E, class F> 
G fun(H<E> he, F& f){ ... }

... many other versions of fun
Run Code Online (Sandbox Code Playgroud)

现在假设我想要同时重命名(或别名,或转发为更精确)这些函数(即能够为同一函数使用不同的名称而不重写它).这样,在代码的其他部分,我可以使用不同的名称,而无需修改上述代码.

这是正确的方式重命名(别名/转发)fungun

template<typename... Args> 
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
    return fun(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
  • 它真的一般吗?
  • 这是最简单的方法吗?
  • 这是最佳方式吗?(例如可以内联,没有不必要的副本)
  • 如果原始功能有一些SFINAE功能怎么办?(例如template<class A, class B, class C, class = std::enable_if< ... >::type>),是否会decltype在所有情况下转移SFINAE? …

c++ templates variadic-templates perfect-forwarding c++11

20
推荐指数
1
解决办法
1810
查看次数

std :: forward <T>和std :: forward <decltype(t)>之间有什么区别?

这些功能相同吗?

template <class T>
void foo(T && t)
{
    bar(std::forward<T>(t));
}

template <class T>
void foo2(T && t)
{
    bar(std::forward<decltype(t)>(t));
}

template <class T>
void foo3(T && t)
{
    bar(std::forward(t));
}
Run Code Online (Sandbox Code Playgroud)

如果是,我可以一直使用这个宏来完美转发吗?

#define MY_FORWARD(var) std::forward<decltype(var)>(var)
Run Code Online (Sandbox Code Playgroud)

或者只是使用

bar(std::forward(t));
Run Code Online (Sandbox Code Playgroud)

我相信foo2并且foo3是一样的,但是我发现人们总是像前进一样使用foo,有没有理由明确写出类型?

据我所知,TT&&两种不同的类型,但我认为std::forward<T>std::forward<T&&>始终给予同样的结果?


编辑:

我想使用宏的原因是我想在以下C++ 1y代码上保存一些打字,我在不同的地方有很多类似的代码

#define XLC_FORWARD_CAPTURE(var) var(std::forward<decltype(var)>(var))
#define XLC_MOVE_CAPTURE(var) var(std::move(var))

template <class T, class U>
auto foo(T && func, U && para )
{
    auto val = // …
Run Code Online (Sandbox Code Playgroud)

c++ perfect-forwarding c++11

20
推荐指数
1
解决办法
1610
查看次数

这是转发参考吗?

在这个例子中,Scott Meyers明确了rvalue引用和转发引用之间的区别:

Widget&& var1 = someWidget;     // here, “&&” means rvalue reference (1)

auto&& var2 = var1;             // here, “&&” does not mean rvalue reference (2)

template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)

template<typename T>
void f(T&& param);              // here, “&&”does not mean rvalue reference (4)
Run Code Online (Sandbox Code Playgroud)

本质上,当我们有一个可推导的上下文时就会出现这种区别,因此案例(3)明确表明我们有一个,vector<...>&&T案例(4)是要推断的,并且(在应用参考折叠规则之后)按"价值类别"分类.

但是更复杂的模式匹配会发生什么?以下面的情况为例:

template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{

}
Run Code Online (Sandbox Code Playgroud)

&&这里的意思是什么?

c++ perfect-forwarding c++11 forwarding-reference

20
推荐指数
2
解决办法
2994
查看次数

如何完善转发成员变量

请考虑以下代码:

template<typename T> void foo(T&& some_struct)
{
    bar(std::forward</* what to put here? */>(some_struct.member));
}
Run Code Online (Sandbox Code Playgroud)

在转发整个结构的情况下,我会这样做std::forward<T>(some_struct).但是如何在转发会员时获得正确的类型?

我有一个想法是使用decltype(some_struct.member),但似乎总是产生该成员的基本类型(如结构定义中所定义).

c++ perfect-forwarding

20
推荐指数
3
解决办法
1086
查看次数