推断类型,而浮动移动/副本无宏
Inferring types whilst eliding moves/copies without a macro
考虑以下简单的make_pair
类:
template <class X, class Y>
struct Pair
{
X x;
Y y;
};
另外,我们将举行一个简单的课程来显示任何动作/副本:
struct C
{
C(int n_) : n(n_) {};
C(const C& x) { n = x.n; std::cout << "Copy: " << n << std::endl; }
C(C&& x) { n = x.n; std::cout << "Move: " << n << std::endl; }
int n;
};
我们可以运行:
auto z1 = Pair<C, C>{C(1),C(2)};
也没有输出,C
未移动或复制。
但是,我们必须指定构造函数Pair
中的类型。可以说我们想推断这些。我们可以做这样的事情:
template <class X, class Y>
Pair<X, Y> make_pair(X&& x, Y&& y)
{
return Pair<X, Y>{std::forward<X>(x), std::forward<Y>(y)};
}
然后我们可以做:
auto z2 = make_pair(C(3),C(4));
但这打印:
Move: 3
Move: 4
如果C
是堆分配的类型,则不是问题,但是如果堆栈分配的类型,移动基本上是副本。
,但是让我们定义此宏:
#define MAKE_PAIR(x,y) decltype(make_pair(x,y)){x,y}
然后我们可以做:
auto z3 = MAKE_PAIR(C(5),C(6));
这确实键入扣除,不需要移动。但是我们需要制作一个宏,我觉得这有点混乱,也阻止了我们使用操作员做这种事情。
是否有以下解决方案:
(1)推论类型(例如2和3)
(2)不需要副本或移动(例如1和3)
(3)不需要宏(例如1和2)
我能得到的最好的是三分之二,但是三分之二可以吗?我无法想象C 会迫使一个人使用宏来获得我所追求的行为,因为C 显然正在远离宏。
。代码在这里。
我无法想象C 会迫使一个人使用宏来获得我所追求的行为,因为C 显然正在远离宏。
首先,标准从未保证过您追求的行为。ELISION是优化;任何实施都不需要。因此,没有一个人可以保证做您想做的事,尽管显然其中一些至少可以允许它。
转发有效地使ELINION不可能;关于这个事实,无能为力。完美的转发与参考和参考折叠有关;ELISION是关于初始化值参数的值,它在初始呼叫站点上不知道。
在现实情况下,这不是问题。实际上值得一试的大多数事情都是复制为昂贵的东西。复制几个int
S或floats
,尤其是对于琐碎的类别,甚至可能不会以剖面的效果出现。在绝大多数情况下,复制昂贵的对象之所以如此,是因为它们拥有某种资源,例如分配的内存。因此,大多数昂贵的类型的复制类型也可能是可移动的,因此会廉价移动。
无论如何,是的,如果您想具有责任的可能性,则不能使用转发。
在您的示例中,您仍然必须指定一次类型。如果您的目标是避免必须多次指定类型,则可以执行此操作:
auto z = Pair<C,C>{3,4};
请注意,如果您有更复杂的结构:
,这甚至有效struct C {
C(int,int) { }
C(int) { }
};
auto z = Pair<C,C>{{1,2},3};
并且不需要副本。
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 用callgrind追踪不必要的副本
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- std::任何只用于移动的模板,其中副本ctor内的static_assert等于编译错误,但为什么
- 按值副本返回,而不是移动
- 移动语义是否只是一个浅层副本并将其他人的指针设置为 null?
- 为什么要进行临时副本所需的移动语义
- 分开副本/移动分配操作员
- 该代码调用副本或移动构造函数
- 推断类型,而浮动移动/副本无宏
- 将 QFile::copy 创建创建文件的副本或将内容从一个文件移动到另一个文件
- GCC C++11 删除移动可分配类的副本分配会阻止 std::sort 编译
- std::在没有提供副本的情况下,使用不安全的移动调整矢量大小