以下代码如何工作以每次为唯一调用堆栈唯一实例化模板函数?
How does the following code work to uniquely instantiate a template function everytime for a unique call-stack?
我遇到了以下来自虚幻引擎源代码
的代码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::OptionallyLogFormattedEnsureMessageReturningFalse
的UE4Asserts_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([]{})
时都可以获得唯一的实例化。
相关文章:
- 何时在引用或唯一指针上使用移动语义
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 计算排序向量的向量中唯一值的计数
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 通过组合不同的类型来创建唯一的id
- 使用Unique_ptr确保工厂中的对象唯一
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- c++多进程编写一个唯一的文件
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 如何更改唯一指针向量的可见性
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 以下代码如何工作以每次为唯一调用堆栈唯一实例化模板函数?
- 唯一指针是否在堆或堆栈上分配内存?
- 尝试使用 VS2015 和 addrinfoW 返回唯一指针时堆栈溢出
- 唯一元素堆栈的容器
- 链接堆栈中的唯一指针