我无法通过 C++ 中的函数式编程重现函数记忆
I can't reproduce the function memoization from Functional Programming in C++
下面的代码应该几乎是 C++ 函数式编程 在第 6 章第 1 节末尾呈现的内容的副本:
#include <iostream>
#include <utility>
#include <mutex>
template<typename F>
class lazy_val {
private:
F m_computation;
mutable decltype(m_computation()) m_cache;
mutable std::once_flag m_value_flag;
public:
lazy_val(F f)
: m_computation(f)
{}
operator const decltype(m_computation())& () const {
std::call_once(m_value_flag, [this](){
m_cache = m_computation();
});
return m_cache; // the execution never gets to this line
}
};
int expensive() {
std::cout << "expensive call...\n";
return 7;
}
int main() {
std::cout << "non memoized" << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
const auto expensive_memo = lazy_val(expensive);
std::cout << "memoized" << '\n';
std::cout << expensive_memo << '\n'; // crash happens here
std::cout << expensive_memo << '\n';
std::cout << expensive_memo << '\n';
}
然而,当我执行它时(编译正常),我得到这个错误:
non memoized
expensive call...
7
expensive call...
7
expensive call...
7
memoized
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
如果忽略并发问题,只依赖初始化为 false
的 mutable bool m_cache_initialized;
和 if (!m_cache_initialized) { m_cache = m_computation(); m_cache_initialized = true; }
,那么一切正常。
这让我觉得问题在于我在代码中使用 std::call_once
/std::once_flag
的方式。但是我看不出它与书中显示的内容有何不同(清单 6.2 中的构造函数,但没有将 m_cache_initialized
初始化为 false
的行,其余的 class 位于第 125 页底部和第 126 页顶部)。
您必须使用 Linux 和 gcc。此实现的一个“未记录”功能是任何使用任何 thread-related 内容的 C++ 代码都必须与 -lpthread
.
显式链接
我在编译(使用 -std=c++17
)和不使用 -lpthread
的情况下链接后,在 Linux 上重现了您的确切崩溃。如果与 -lpthread
.
显式链接,则显示的代码运行良好
下面的代码应该几乎是 C++ 函数式编程 在第 6 章第 1 节末尾呈现的内容的副本:
#include <iostream>
#include <utility>
#include <mutex>
template<typename F>
class lazy_val {
private:
F m_computation;
mutable decltype(m_computation()) m_cache;
mutable std::once_flag m_value_flag;
public:
lazy_val(F f)
: m_computation(f)
{}
operator const decltype(m_computation())& () const {
std::call_once(m_value_flag, [this](){
m_cache = m_computation();
});
return m_cache; // the execution never gets to this line
}
};
int expensive() {
std::cout << "expensive call...\n";
return 7;
}
int main() {
std::cout << "non memoized" << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
std::cout << expensive() << '\n';
const auto expensive_memo = lazy_val(expensive);
std::cout << "memoized" << '\n';
std::cout << expensive_memo << '\n'; // crash happens here
std::cout << expensive_memo << '\n';
std::cout << expensive_memo << '\n';
}
然而,当我执行它时(编译正常),我得到这个错误:
non memoized
expensive call...
7
expensive call...
7
expensive call...
7
memoized
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
如果忽略并发问题,只依赖初始化为 false
的 mutable bool m_cache_initialized;
和 if (!m_cache_initialized) { m_cache = m_computation(); m_cache_initialized = true; }
,那么一切正常。
这让我觉得问题在于我在代码中使用 std::call_once
/std::once_flag
的方式。但是我看不出它与书中显示的内容有何不同(清单 6.2 中的构造函数,但没有将 m_cache_initialized
初始化为 false
的行,其余的 class 位于第 125 页底部和第 126 页顶部)。
您必须使用 Linux 和 gcc。此实现的一个“未记录”功能是任何使用任何 thread-related 内容的 C++ 代码都必须与 -lpthread
.
我在编译(使用 -std=c++17
)和不使用 -lpthread
的情况下链接后,在 Linux 上重现了您的确切崩溃。如果与 -lpthread
.