, ++ 14, , .
template<class T>
struct Factory {
template<class...Args>
Factory(Args&&... args):
creator_(
make_creator(
std::index_sequence_for<Args...>{},
std::make_tuple( std::forward<Args>(args)...
)
)
{}
std::shared_ptr<T> operator()() const {
return creator_();
}
private:
using signature = std::shared_ptr<T>();
using creator = std::function<signature>;
creator creator_;
template<class Tup, size_t...Is>
static creator make_creator(std::index_sequence<Is...>, Tup&& tup) {
return [tup = std::forward<Tup>(tup)]{
return std::make_shared<T>( std::get<Is>(tup)... );
};
}
};
.
-, , T :
Factory<Foo> f1(true);
Factory<Bar> f2("string");
-, f1.Create() f1(). factory , factory - - .
:
template<class T>
using Factory = std::function<std::shared_ptr<T>()>;
namespace details {
template<class T, class Tup, size_t...Is>
Factory<T> make_factory(std::index_sequence<Is...>, Tup&& tup) {
return [tup = std::forward<Tup>(tup)]{
return std::make_shared<T>( std::get<Is>(tup)... );
};
}
}
template<class T, class...Args>
Factory<T> make_factory(Args&&...args) {
return details::make_factory<T>(
std::index_sequence_for<Args...>{},
std::make_tuple( std::forward<Args>(args)... )
);
}
Factory - Factory<T> std::function, shared_ptr<T>.
.
details::make_factory .
namespace details {
template<class F, class Tup, size_t...Is>
auto invoke( F&& f, Tup&& tup, std::index_sequence<Is...> )
-> std::result_of_t<F( std::tuple_element_t<Is, std::decay_t<Tup>>... )>
{
return std::forward<F>(f)( std::get<Is>(std::forward<Tup>(tup))... );
}
}
template<class F, class Tup, size_t...Is>
auto invoke( F&& f, Tup&& tup )
{
using count = std::tuple_size< std::decay_t<Tup> >;
using indexes = std::make_index_sequence< count{} >;
return details::invoke(
std::forward<F>(f),
std::forward<Tup>(tup),
indexes{}
);
}
template<class T>
auto shared_maker() {
return [](auto&&...args){
return std::make_shared<T>( decltype(args)(args)... );
};
}
template<class T, class...Args>
Factory<T> make_factory(Args&&...args) {
return [tup=std::make_tuple(std::forward<Args>(args)...)]{
return invoke(
shared_maker<T>(),
tup
);
};
}
, " " invoke .
template<class T>
const auto shared_maker = [](auto&&...args){
return std::make_shared<T>(decltype(args)(args)...);
};
, gcc 5.2.0 .