【发布时间】:2015-09-25 04:26:43
【问题描述】:
我想创建一个宏,将一对解包成两个局部变量。如果它只是一个变量,我不想创建该对的副本,这将完成:
#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 id = [](auto&& x) -> decltype(auto) { return decltype(x)(x); }; auto&& tmp = id(5);之类的东西调用UB,但它不为auto&& tmp = 5;调用UB——这与绑定到引用的临时对象的生命周期的延长有关。您是否需要通过宏保持值V有效?auto tmp = V;也保持其价值,除非它存在内部生命周期问题。 -
@dyp:是的,我想保持该值有效,而不复制它(如果给定一个局部变量,
auto tmp = V会这样做) -
This 可能是相关的。
-
我真的不清楚你想做什么。你想获得对中每个成员的引用吗?为什么?为了什么?有什么限制?为什么是宏?
-
用例是什么?您想为
.first和.second成员取更好的名字吗?您想通过更短的名称更轻松地访问吗?
标签: c++ c++11 macros undefined-behavior forwarding-reference