以下代码如何工作以每次为唯一调用堆栈唯一实例化模板函数?

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

本文关键字:唯一 堆栈 调用 实例化 函数 代码 何工作 工作      更新时间:2023-10-16

我遇到了以下来自虚幻引擎源代码

的代码
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)时,要FDebug::OptionallyLogFormattedEnsureMessageReturningFalseUE4Asserts_Private::TrueFirstCallOnly参数仅在第一次为特定调用堆栈调用时计算为 true(我正在考虑每个调用堆栈,因为TrueOnFirstCallOnly在下一次调用时评估为 false 以确保来自同一调用堆栈,但触发来自不同调用堆栈的确保,但不是很确定(,我不明白这是如何工作的。

正如他们在评论中所说,以某种方式将 lambda[]{}传递给模板函数会唯一地实例化它。它是如何工作的?作为模板传递的 lambda 真正唯一是为了什么,它是调用堆栈还是其他什么?

如果表达式为真,则可以认为LIKELY(!!(InExpression))的计算结果为 true

这就是实现这种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表达式相同([]{}vs[]{}(,它们也是不同类型的。另一方面,相同的 lambda 表达式(即第一次调用foo时的表达式和第二次调用foo时的表达式(属于同一类型。这样,每次编写get_true_on_first_call([]{})时都可以获得唯一的实例化。