簡體   English   中英

C variadic宏調用另一個可變參數宏

[英]C variadic macro call another variadic macro

我有以下代碼(按原樣):

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 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM