簡體   English   中英

以下代碼如何為唯一的調用堆棧每次都唯一地實例化模板函數?

[英]How does the following code work to uniquely instantiate a template function everytime for a unique call-stack?

我遇到了以下來自Unreal Engine源代碼的代碼

namespace UE4Asserts_Private
{
    // This is used by ensure to generate a bool per instance
    // by passing a lambda which will uniquely instantiate the template.
    template <typename Type>
    bool TrueOnFirstCallOnly(const Type&)
    {
        static bool bValue = true;
        bool Result = bValue;
        bValue = false;
        return Result;
    }

    FORCEINLINE bool OptionallyDebugBreakAndPromptForRemoteReturningFalse(bool bBreak, bool bIsEnsure = false)
    {
        if (bBreak)
        {
            FPlatformMisc::DebugBreakAndPromptForRemoteReturningFalse(bIsEnsure);
        }
        return false;
    }
}

#define ensure(           InExpression                ) (LIKELY(!!(InExpression)) || FDebug::OptionallyLogFormattedEnsureMessageReturningFalse(UE4Asserts_Private::TrueOnFirstCallOnly([]{}), #InExpression, __FILE__, __LINE__, TEXT("")               ) || UE4Asserts_Private::OptionallyDebugBreakAndPromptForRemoteReturningFalse(UE4Asserts_Private::TrueOnFirstCallOnly([]{}), true))

現在,每當我們使用ensure(SomeExpression)UE4Asserts_Private::TrueFirstCallOnly參數FDebug::OptionallyLogFormattedEnsureMessageReturningFalse計算結果為真實的,只有在第一次被調用特定的調用堆棧(我每次調用堆棧想,作為TrueOnFirstCallOnly計算結果為假的下一次調用來自同一調用堆棧的確保,但從不同的調用堆棧觸發確保但不是很確定),我不明白這是如何工作的。

正如他們在評論中所述,以某種方式將 lambda []{}傳遞給模板函數會唯一地實例化它。 它是如何工作的? 什么是作為模板傳遞的 lambda 真正獨特的,它是調用堆棧還是其他什么?

如果表達式為真,則LIKELY(!!(InExpression))可以被認為評估為真

這就是如何實現這樣的true_on_first_call

include <iostream>

template <typename T> struct true_on_first_call {
    static bool first;
    bool operator()() {
        if (first) {
            first = false;
            return true;
        }
        return false;
    }
};
template <typename T> bool true_on_first_call<T>::first = true;
template <typename T> 
bool get_true_on_first_call(const T &){ return true_on_first_call<T>()(); }

void foo() {
    std::cout << get_true_on_first_call([]{}) << "\n";    // instantiation for []{}
}
void bar() {
    std::cout << get_true_on_first_call([]{}) << "\n";    // instantiation for []{}
}                                                         // note: its a different type 
                                                          // than the []{} above!
                                                          // but the same on 
                                                          // repeated calls to foo


int main() {
    std::cout << "first \n";
    foo();
    bar();
    std::cout << "second \n";
    foo();
    bar();
}

現場演示

訣竅是每個 labmda 表達式都有一個唯一的類型,因此它會導致true_on_first_call的不同實例化。 即使 lambdas 表達式相同( []{}[]{} ),它們的類型也不同。 另一方面,相同的 lambda 表達式(即第一次調用foo表達式和第二次調用foo表達式)是相同的類型。 通過這種方式,您每次編寫get_true_on_first_call([]{})時都可以獲得唯一的實例化。

暫無
暫無

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

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