你知道如何对字符串进行延迟评估,就像在这个D片段中一样:
void log(lazy string msg) {
static if (fooBarCondition)
writefln(…) /* something with msg */
}
实际上,问题可能根本不需要懒惰,因为 static if。也许有可能在不使用时丢弃char const*
字符串?就像在C ++中一样:
void log(char const *msg) {
#ifdef DEBUG
cout << … << endl; /* something with msg */
#else /* nothing at all */
#endif
}
有什么想法吗?谢谢。
答案 0 :(得分:5)
#ifdef DEBUG
#define log(msg) do { cout << … << endl; } while(0)
#else
#define log(msg) do { } while(0)
#endif
在C ++ 11中有两种方法可以实现懒惰:宏和lambda表达式。两者在技术上都不是“懒惰”,而是所谓的“正常评估”(与“急切评估”相对),这意味着表达式可能被评估任意次。因此,如果您要将程序从D(或haskell)转换为C ++,则必须注意不要在这些表达式中使用带副作用的表达式(包括计算时间)。
要实现真正的懒惰,你必须实现记忆,这不是那么简单。
对于简单的日志记录,宏很好。
答案 1 :(得分:3)
您可以混合使用宏和lambda来创建此效果
你可以有一个类型,懒惰
template<class T>
class lazy {
...
}
然后你可以使用一个LAZY包装器,使用lambda
创建其中一个#define LAZY(E) my_lazy_type<decltype((E))>([&](){ return E; })
所有my_lazy_type需求都是一个接受std :: function的构造函数,以及一个运算符()的重载,它会计算并返回它。在每次评估时,您可以使用只返回已计算值的thunk替换thunk,因此只会计算一次。
编辑: 这是我所说的一个例子。但我想指出这不是一个完美的例子。它在懒惰的一边传递了一堆东西,这可能完全打败了这一切的目的。它在内部使用mutable因为我需要能够在const情况下记忆thunk。这可以通过很多方式得到改善,但它是一个不错的概念证明。
#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;
}
答案 2 :(得分:0)
虽然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
}
只需2美分。