这里需要实现的是在 v 宏参数的扩展中检测 &&,但如果它嵌套在 ()" 中则不是。
不,这是不可能的。我建议在单独的参数中将类型与名称分开。
OUTCOME_TRYA_NEW(auto, x, expr);
OUTCOME_TRYA_NEW(auto &&, x, expr);
您可以使用 stringify 将检测移至运行时,例如:
#define OUTCOME_TRYA(v, ...) \
if constexpr (your_constexpr_strstr(#v, "&&")) { \
/* do stuff with `auto &&` here */ \
} else { \
/* do stuff with `auto` here */ \
}
(或者我认为也有一些std::is_same(decltype(v)....) 的东西),但是当您想在宏扩展中声明变量时,我认为这没有帮助。
您可以使用的另一种方法是将第一个参数的扩展延迟到稍后阶段,以便您可以在参数数量上重载它,如下所示:
// Add a comma. But later.
#define OUTCOME_REF(name) &&, name
#define OUTCOME_TRYA_CHOOSE_1(name, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name, ...) \
auto &&unique1 = (__VA_ARGS__); name = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(name __VA_ARGS__)
// ^^^^^^ I have no idea why it works without a comma, but it does. It's scary.
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE(...) \
OUTCOME_TRYA_CHOOSE_N(__VA_ARGS__,2,1)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name)(name, __VA_ARGS__)
// ^^^^ - overload on number of arguments in expansion of first parameter
OUTCOME_TRYA(auto x, expr1) // auto unique0 = (expr1); auto x = std::move(unique0).value();
OUTCOME_TRYA(auto OUTCOME_REF(x), expr2) // auto &&unique1 = (expr2); auto && x = std::move(unique1).value();
以类似的方式,您可以将界面无缝重构为:
#define UNPACK(...) __VA_ARGS__
#define OUTCOME_TRYA_CHOOSE_1(name, nameunpacked, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name1, name2, ...) \
auto &&unique1 = (__VA_ARGS__); name1 name2 = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,_3,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE(n, ...) \
OUTCOME_TRYA_CHOOSE_N(n, __VA_ARGS__, 2, 1)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name, UNPACK name)(name, UNPACK name, __VA_ARGS__)
OUTCOME_TRYA(auto x, expr1, expr2)
OUTCOME_TRYA((auto &&, x), expr3, expr4)
上面看起来不错,并且允许保留当前界面。诀窍在于OUTCOME_TRYA_CHOOSE(name, UNPACK name) - 当name 是(something, something) 时,OUTCOME_TRYA_CHOOSE_N 传递了 3 个参数,如果不是,则传递 2 个参数 - 然后可以在参数数量上重载。因此,如果输入包含带有逗号的大括号,它会有效地重载。
我想你不知道实现 OUTCOME_TRYV((auto &&), expr1, expr2) 的方法
嗯;p。解包时添加逗号,有效地将重载转移到另一个。
#define UNPACK_ADD_COMMA(...) ,__VA_ARGS__
#define OUTCOME_TRYA_CHOOSE_1(name, nameunpacked, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name1, ...) \
OCH_MY_GOD()
#define OUTCOME_TRYA_CHOOSE_3_IN(name1, name2, ...) \
auto &&unique1 = (__VA_ARGS__); name1 name2 = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_3(name, ignore, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_3_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,_3,_4,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE_IN(n, ...) \
OUTCOME_TRYA_CHOOSE_N(n, __VA_ARGS__, 3, 2, 1)
#define OUTCOME_TRYA_CHOOSE(n, ...) \
OUTCOME_TRYA_CHOOSE_IN(n, __VA_ARGS__)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name, UNPACK_ADD_COMMA name)(name, UNPACK_ADD_COMMA name, __VA_ARGS__)
OUTCOME_TRYA(auto x, expr1, expr2)
OUTCOME_TRYA((auto &&, x), expr3, expr4)
OUTCOME_TRYA((auto &&), expr3, expr4)