C++ C+中的懒惰+;11
您知道如何对字符串执行惰性求值吗,如下面的D代码段:C++ C+中的懒惰+;11,c++,c++11,d,lazy-evaluation,C++,C++11,D,Lazy Evaluation,您知道如何对字符串执行惰性求值吗,如下面的D代码段: void log(lazy string msg) { static if (fooBarCondition) writefln(…) /* something with msg */ } 实际上,问题可能根本不需要懒惰,因为静态if。不使用时,是否可以丢弃char const*字符串?比如,在C++中: void log(char const *msg) { #ifdef DEBUG cout << … &
void log(lazy string msg) {
static if (fooBarCondition)
writefln(…) /* something with msg */
}
实际上,问题可能根本不需要懒惰,因为静态if。不使用时,是否可以丢弃char const*
字符串?比如,在C++中:
void log(char const *msg) {
#ifdef DEBUG
cout << … << endl; /* something with msg */
#else /* nothing at all */
#endif
}
void日志(char const*msg){
#ifdef调试
无法#ifdef调试
#define log(msg)do{cout虽然Elazar的答案有效,但我不喜欢为此使用宏(尤其是那些名称都是小写的宏)。
以下是我将要做的:
template<bool /* = false */>
struct logger_impl {
template<typename T>
static std::ostream & write(std::ostream & stream, T const &) {
return stream;
}
};
template<>
struct logger_impl<true> {
template<typename T>
static std::ostream & write(std::ostream & stream, T const & obj) {
return stream << obj;
}
};
template<typename T>
void log(T const & obj) {
#if defined(NDEBUG)
logger_impl<true>::write(std::cout, obj);
#else
logger_impl<false>::write(std::cout, obj);
#endif
}
模板
结构记录器\u impl{
模板
静态std::ostream&write(std::ostream&stream,T const&){
回流;
}
};
模板
结构记录器\u impl{
模板
静态std::ostream和write(std::ostream和stream、T const和obj){
返回流您可以混合使用宏和lambda来创建此效果
你可以有一个类型,懒惰
template<class T>
class lazy {
...
}
模板
班级懒惰{
...
}
然后你可以有一个懒惰的包装器,它使用lambda创建了其中的一个
#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
#定义LAZY(E)my_LAZY_类型([&](){return E;})
我的_lazy_类型所需要的只是一个接受std::函数的构造函数,以及一个重载运算符(),用于计算并返回该函数。在每次计算中,您可以使用只返回已计算值的thunk替换thunk,因此它只会被计算一次
编辑:
这是一个我正在谈论的例子。然而,我想指出,这不是一个完美的例子。它在懒惰的一方传递了一堆东西的价值,这可能完全违背了一开始做这一切的目的。它在这里面使用mutable,因为我需要能够在常量情况下记住thunk。这s可以在很多方面得到改进,但这是一个不错的概念证明
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#define LAZY(E) lazy<decltype((E))>{[&](){ return E; }}
template<class T>
class lazy {
private:
struct wrapper {
std::function<T()> thunk;
wrapper(std::function<T()>&& x)
: thunk(std::move(x)) {}
wrapper(const std::function<T()>& x)
: thunk(x) {}
};
//anytime I see mutable, I fill a bit odd
//this seems to be warented here however
mutable std::shared_ptr<wrapper> thunk_ptr;
public:
lazy(std::function<T()>&& x)
: thunk_ptr(std::make_shared<wrapper>(std::move(x))) {}
T operator()() const {
T val = thunk_ptr->thunk();
thunk_ptr->thunk = [val](){return val;};
return val;
}
};
void log(const lazy<std::string>& msg) {
std::cout << msg() << std::endl;
}
int main() {
std::string hello = "hello";
std::string world = "world";
log(LAZY(hello + ", " + world + "!"));
return 0;
}
#包括
#包括
#包括
#包括
#定义LAZY(E)LAZY{[&](){return E;}}
模板
班级懒惰{
私人:
结构包装器{
std::函数thunk;
包装器(std::function&&x)
:thunk(std::move(x)){}
包装器(const std::function&x)
:thunk(x){}
};
//每当我看到易变,我都会填充一点奇怪的内容
//然而,这似乎在这里得到了证实
可变std::共享\u ptr thunk\u ptr;
公众:
惰性(std::函数和&x)
:thunk_ptr(std::make_shared(std::move(x))){
T运算符()()常量{
T val=thunk_ptr->thunk();
thunk_ptr->thunk=[val](){return val;};
返回val;
}
};
无效日志(const lazy&msg){
std::cout这是获得“惰性评估”的方法,除非你想搞乱lambdas。我认为你不想在日志记录中这样做。像IMO这样做的最好方法是宏,以避免在不需要时构建要传递的消息。(请参阅断言宏)如果
看起来inviting@CaptainObvlious,它是一个D
元编程feature@skp我知道。它仍然是吸引人的。@ CoptObViLy:它已经被提议给C++标准委员会,我不确定它会因为一些更深的含义而飞。当前的C++允许通过代码>类似的IFIFF < /COD>类似的事情。,但ifdef在预处理时求值,而static if
是编译时求值(即,可以使用模板、常量--不仅仅是其他定义--…此IfThenElse模板非常有用,但它不是惰性的。log(exp)中的表达式每次都会对
进行评估,即使没有定义
NDEBUG
。谢谢你,但是对于记录东西来说,你不觉得这太过分了吗?当然,这太过分了,我是在回答如何实现懒惰的问题。如果你的目标只是记录,我真的不明白你为什么需要懒惰。@Jake whywrapper
是一个好主意eded?难道就不能有std::shared\u ptr
到std::function
?我已经完全忘记了我当时的想法,然后说实话。现在看它看起来很傻。我在这里写了另一个版本,似乎我在那个版本中删除了它。我不记得我当时在想什么。它看起来像是我的设计专业版的人工制品直到后来我才拿出来的东西。
#include <iostream>
#include <functional>
#include <memory>
#include <string>
#define LAZY(E) lazy<decltype((E))>{[&](){ return E; }}
template<class T>
class lazy {
private:
struct wrapper {
std::function<T()> thunk;
wrapper(std::function<T()>&& x)
: thunk(std::move(x)) {}
wrapper(const std::function<T()>& x)
: thunk(x) {}
};
//anytime I see mutable, I fill a bit odd
//this seems to be warented here however
mutable std::shared_ptr<wrapper> thunk_ptr;
public:
lazy(std::function<T()>&& x)
: thunk_ptr(std::make_shared<wrapper>(std::move(x))) {}
T operator()() const {
T val = thunk_ptr->thunk();
thunk_ptr->thunk = [val](){return val;};
return val;
}
};
void log(const lazy<std::string>& msg) {
std::cout << msg() << std::endl;
}
int main() {
std::string hello = "hello";
std::string world = "world";
log(LAZY(hello + ", " + world + "!"));
return 0;
}