如何创建一个多次使用一个值而不复制它的宏?
How can I create a macro which uses a value multiple times, without copying it?
我想创建一个宏,将一对变量解包为两个局部变量。如果它只是一个变量,我不想创建该对的副本,这将完成:
#define UNPACK_PAIR(V1, V2, PAIR) \
auto& V1 = PAIR.first; \
auto& V2 = PAIR.second;
UNPACK_PAIR(one, two, x);
但是,我也希望它不要计算多次给出的表达式,例如这应该只调用 expensive_computation()
一次:
UNPACK_PAIR(one, two, expensive_computation());
如果我这样做:
#define UNPACK_PAIR_A(V1, V2, PAIR) \
auto tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
然后它适用于 expensive_computation()
的情况,但它在 x
的情况下复制。如果我这样做:
#define UNPACK_PAIR_R(V1, V2, PAIR) \
auto& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
然后它在 x
情况下工作而不制作副本但在 expensive_computation()
情况下失败。如果我这样做:
#define UNPACK_PAIR_CR(V1, V2, PAIR) \
const auto& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
这些都可以编译 运行,但我怀疑它们会调用未定义的行为 - 我对此是否正确?另外,这两个有什么意义吗?
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = std::move(PAIR); \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = std::forward<decltype(PAIR)>(PAIR); \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
有什么方法可以创建适用于这两种用例的宏 - 不复制 x
但在给定表达式或函数调用的结果时也不调用未定义的行为?
你不需要宏。
auto p = std::make_pair(2, 3);
int x, y;
std::tie(x, y) = p;
如果您想要引用一对中的现有成员:
auto p = std::make_pair(2, 3);
auto& x = p.first;
auto& y = p.second;
就是这样。
现在您可以继续做更多的事情了challenging/interesting/important。
auto&&
创建转发引用,即它接受任何内容。它 而不是 (总是)创建一个右值引用。所以就这样做:
#define UNPACK_PAIR(V1, V2, PAIR) \
auto&& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
但是,我强烈建议不要这样做(除非UNPACK_PAIR
的使用范围非常有限,并且在该范围内确实无处不在。看起来默默无闻对我没有真正的好处。想象一下 6 个月后返回项目,只需两个小时就可以找到一个严重的错误。您会感谢自己使用非标准的基于宏的语法而不是可读的语法吗?
你要的是std::tie
.
decltype(p.first) x;
decltype(p.second) y;
std::tie(x,y) = p;
如果需要,您甚至可以使用它来定义您的宏。请注意,这仅适用于 2 元组 - 如果您想要 3 元组或更多元组,则需要做一些不同的事情。例如,如果您有一个 3 元组 t
:
decltype(std::get<0>(t)) x;
decltype(std::get<1>(t)) y;
decltype(std::get<2>(t)) z;
std::tie(x,y,z) = t;
我想创建一个宏,将一对变量解包为两个局部变量。如果它只是一个变量,我不想创建该对的副本,这将完成:
#define UNPACK_PAIR(V1, V2, PAIR) \
auto& V1 = PAIR.first; \
auto& V2 = PAIR.second;
UNPACK_PAIR(one, two, x);
但是,我也希望它不要计算多次给出的表达式,例如这应该只调用 expensive_computation()
一次:
UNPACK_PAIR(one, two, expensive_computation());
如果我这样做:
#define UNPACK_PAIR_A(V1, V2, PAIR) \
auto tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
然后它适用于 expensive_computation()
的情况,但它在 x
的情况下复制。如果我这样做:
#define UNPACK_PAIR_R(V1, V2, PAIR) \
auto& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
然后它在 x
情况下工作而不制作副本但在 expensive_computation()
情况下失败。如果我这样做:
#define UNPACK_PAIR_CR(V1, V2, PAIR) \
const auto& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
这些都可以编译 运行,但我怀疑它们会调用未定义的行为 - 我对此是否正确?另外,这两个有什么意义吗?
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = std::move(PAIR); \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
#define UNPACK_PAIR_RR(V1, V2, PAIR) \
auto&& tmp = std::forward<decltype(PAIR)>(PAIR); \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
有什么方法可以创建适用于这两种用例的宏 - 不复制 x
但在给定表达式或函数调用的结果时也不调用未定义的行为?
你不需要宏。
auto p = std::make_pair(2, 3);
int x, y;
std::tie(x, y) = p;
如果您想要引用一对中的现有成员:
auto p = std::make_pair(2, 3);
auto& x = p.first;
auto& y = p.second;
就是这样。
现在您可以继续做更多的事情了challenging/interesting/important。
auto&&
创建转发引用,即它接受任何内容。它 而不是 (总是)创建一个右值引用。所以就这样做:
#define UNPACK_PAIR(V1, V2, PAIR) \
auto&& tmp = PAIR; \
auto& V1 = tmp.first; \
auto& V2 = tmp.second;
但是,我强烈建议不要这样做(除非UNPACK_PAIR
的使用范围非常有限,并且在该范围内确实无处不在。看起来默默无闻对我没有真正的好处。想象一下 6 个月后返回项目,只需两个小时就可以找到一个严重的错误。您会感谢自己使用非标准的基于宏的语法而不是可读的语法吗?
你要的是std::tie
.
decltype(p.first) x;
decltype(p.second) y;
std::tie(x,y) = p;
如果需要,您甚至可以使用它来定义您的宏。请注意,这仅适用于 2 元组 - 如果您想要 3 元组或更多元组,则需要做一些不同的事情。例如,如果您有一个 3 元组 t
:
decltype(std::get<0>(t)) x;
decltype(std::get<1>(t)) y;
decltype(std::get<2>(t)) z;
std::tie(x,y,z) = t;