我有以下代码(原样):
template<class T, class FieldT>
using addRefU = typename std::conditional<
std::is_rvalue_reference<T>::value,
typename std::add_rvalue_reference< FieldT >::type,
typename std::conditional<
std::is_rvalue_reference<FieldT>::value,
typename std::add_rvalue_reference< FieldT >::type,
typename std::add_lvalue_reference< FieldT >::type
>::type
>::type;
#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(X,##__VA_ARGS__, 4, 3, 2, 1, 0)
#define VARARG_IMPL2(base, count, ...) base##count(__VA_ARGS__)
#define VARARG_IMPL(base, count, ...) VARARG_IMPL2(base, count, __VA_ARGS__)
#define VARARG(base, ...) VARARG_IMPL(base, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
#define REF2(val, p1) addRefU<decltype(val), decltype(val.p1)>
#define REF3(val, p1, p2) addRefU<decltype(val), decltype(val.p1.p2)>
#define REF4(val, p1, p2, p3) addRefU<decltype(val), decltype(val.p1.p2.p3)>
#define REF5(val, p1, p2, p3, p4) addRefU<decltype(val), decltype(val.p1.p2.p3.p4)>
#define REF(...) VARARG(REF, __VA_ARGS__) // It says REF is not defined here
#define CAST_REF2(val, p1) static_cast<REF(val, p1)>(val.p1)
#define CAST_REF3(val, p1, p2) static_cast<REF(val, p1, p2)>(val.p1.p2)
#define CAST_REF4(val, p1, p2, p3) static_cast<REF(val, p1, p2, p3)>(val.p1.p2.p3)
#define CAST_REF5(val, p1, p2, p3, p4) static_cast<REF(val, p1, p2, p3, p4)>(val.p1.p2.p3.p4)
#define CAST_REF(...) VARARG(CAST_REF, __VA_ARGS__)
struct A{};
struct B{A a;};
int main()
{
B b;
using t = REF(b, a); // Ok
auto &&k = CAST_REF2(b, a); // work
auto &&k1 = CAST_REF(b, a); // NOT work
return 0;
}
http://coliru.stacked-crooked.com/a/8dff49f68b7e15e1
如果我改变
#define CAST_REF2(val, p1) static_cast<REF(val, p1)>(val.p1)
至
#define CAST_REF2(val, p1) static_cast<REF2(val, p1)>(val.p1)
(更改REF
为REF2
)
有用。我不明白为什么我可以REF
直接调用而不能从宏执行此操作。
您的代码(包含在内)将预处理为以下内容:
struct A{};
struct B{A a;};
int main()
{
B b;
using t = addRefU<decltype(b), decltype(b.a)>
auto &&k = static_cast<VARARG(REF, b, a)>(b.a);
auto &&k1 = static_cast<addRefU<decltype(b), decltype(b.a)> >(b.a);
return 0;
}
显然,VARARG
它没有被扩展,这是因为它在的扩展中已经被扩展了CAST_REF
(并非如此CAST_REF2
):
[C++11: 16.3.4/2]:
如果在此替换列表扫描期间找到了要替换的宏的名称(不包括源文件的其余预处理令牌),则不会替换该宏。此外,如果任何嵌套的替换遇到要替换的宏的名称,则不会替换它。这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们稍后(在重新以其他方式替换了该宏名称预处理令牌的情况下)进行了检查。
该规则的目的是禁止无限递归,即使在这种特殊情况下您实际上没有风险。
之前已经在Stack Overflow上对此进行了讨论,但是目前还不确定(如何复制VARARG
除外)如何解决它。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句