這裏有一點點複雜的做你想做的事情。基本想法是讓LazyConstruct
將參數包存儲在tuple
中,然後根據需要解壓tuple
以構建T
。
template<class T, class... Args>
struct LazyConstruct {
// accept any number of arguments,
// which would later be used to construct T
template<class... U>
LazyConstruct(U&&... u)
: args(std::make_tuple(std::forward<U>(u)...))
{
}
T& get() {
if(!data) data = create(std::index_sequence_for<Args...>());
return *data;
}
template<std::size_t... I>
std::unique_ptr<T> create(std::index_sequence<I...>)
{
return std::unique_ptr<T>{new T(std::get<I>(args)...)};
}
private:
std::tuple<typename std::decay<Args>::type...> args;
std::unique_ptr<T> data;
};
我正在使用C++ 14的std::index_sequence
,如果你的標準庫實現不出貨這一點,那麼有上顯示它是如何實現的SO(this或this)的幾個例子。
最後一個輔助函數模板構建LazyConstruct
實例
template<class T, class... Args>
LazyConstruct<T, Args...> make_LazyConstruct(Args&&... args)
{
return LazyConstruct<T, Args...>{std::forward<Args>(args)...};
}
Live demo
基於Alf's answer另一個版本,它使用std::function
,使LazyConstruct
的類型不更改基於T
「的構造函數簽名。
template<class T>
struct LazyConstruct {
template<class... Args>
LazyConstruct(Args&&... args)
: holder([this, args = std::make_tuple(std::forward<Args>(args)...)]() {
return create(std::index_sequence_for<Args...>(), std::move(args));
})
{
}
T& get() {
if(!data) data = holder();
return *data;
}
template<std::size_t... I, class Tuple>
std::unique_ptr<T> create(std::index_sequence<I...>, Tuple args)
{
return std::unique_ptr<T>{new T(std::get<I>(args)...)};
}
private:
std::function<std::unique_ptr<T>()> holder;
std::unique_ptr<T> data;
};
Live demo
你允許假設傳遞的左值的引用將是有效的,當'GET'叫? – Pradhan 2014-10-22 03:48:45
是的。或者更具體地說,如果不是,則行爲是未定義的。 (就像在任何其他情況下的ref綁定) – Nick 2014-10-22 12:58:13