Следующий код прекрасно компилируется под VS2013 и выше, а также GCC
https://godbolt.org/z/-nKXB-
#include "boost/thread/once.hpp"
#include "boost/optional.hpp"
#include <functional>
/// A class to encapsulate lazy initialization of an object.
/// All instances of Lazy are thread safe and the factory
/// is guaranteed only to be called once. However if you
/// use this for member initialization DO NOT capture
/// this in the lambda. See LazyMember for an alternative
template <typename T>
class Lazy {
mutable boost::once_flag _once;
mutable boost::optional<T> _data;
typedef std::function<T()> FactoryFn;
FactoryFn _factory;
void Init() const { boost::call_once([&]() { _data = _factory(); }, _once); }
public:
Lazy(FactoryFn factory):
_once(BOOST_ONCE_INIT),
_factory(factory)
{
}
T& Value() {
Init();
return *_data;
}
};
, который будет использоваться как
Lazy<int> i([]{return 10;}); // Pretend lambda is an expensive op
// and then some time later.
return i.Value()
Тестирование на VS2010Я получаю
1>Lazy.hpp(26):
error C2059: syntax error : ')' 1>
Lazy.hpp(37)
: see reference to class template instantiation 'mw::Lazy<T>' being
compiled
1>Lazy.hpp(26):
error C2059: syntax error : ','
1>Lazy.hpp(28):
error C2334: unexpected token(s) preceding '{'; skipping apparent
function body
Обход, кажется, есть.
/// A class to encapsulate lazy initialization of an object.
/// All instances of Lazy are thread safe and the factory
/// is guaranteed only to be called once. However if you
/// use this for member initialization DO NOT capture
/// this in the lambda. See LazyMember for an alternative
template <typename T>
class Lazy {
mutable boost::once_flag _once;
mutable boost::optional<T> _data;
typedef std::function<T()> FactoryFn;
FactoryFn _factory;
void Init() const { boost::call_once([&]() { _data = _factory(); }, _once); }
public:
Lazy(FactoryFn factory):
_factory(factory)
{
_once = BOOST_ONCE_INIT;
}
T& Value() {
Init();
return *_data;
}
};
Но в чем проблема корня?