Variadic members in non-template class - c++

I'm trying to write a class Invocation which has a templated constructor:
template<typename F>
class Invocation {
public:
template<typename... Args>
Invocation(F&& f, Args&&... args)
{ /* store f and args somewhere for later use */ }
...
};
Normally I would parameterize the Invocation class itself with both F and Args..., but in this case I need a uniform type for a given F, so I'm trying to find a way to store args... of any types inside a Invocation<F>, and to incur as little performance hit as possible. (This might not be the best design, but it can be an interesting exercise.)
One thought is to use virtual functions:
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) = 0;
};
template<typename F, typename... Ts>
class Args : public ArgsBase<F> {
public:
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
void invoke(F&& f) override
{
/* somehow call f with args_ (something like std::apply) */
...
}
private:
std::tuple<Ts&&...> args_;
};
And then in the Invocation<F> class, we can for example have an std::unique_ptr<ArgsBase<F>> member, which points to an Args<F, Ts...> object created in the Invocation<F> ctor. And we can call its invoke virtual method when needed.
This is just one random idea I came up with. Is there any other way to achieve this? Ideally without the overhead of virtual functions or anything like that?
UPDATE: Thanks to the comments/answers that suggest using std::function or lambdas. I should've made it clear that I'm actually interested in a more general case, i.e., the variadic stuff might not be arguments to a callable. It can be just anything that I want to store in a class whose type is not parameterized by the types of these stuff.

As mentioned in comment, I wouldn't worry about storing arguments by value. The compiler's copy-elision can be generous.
Particularly if you offer the class an r-value invoke:
#include <tuple>
template<typename F>
class ArgsBase {
public:
// discard return value
virtual void invoke(F&& f) const & = 0;
virtual void invoke(F&& f) && = 0;
};
template<typename F, class... FunctionArgs>
class Args : public ArgsBase<F> {
public:
template<class...Ts>
Args(Ts&&... args) : args_(std::forward<Ts>(args)...) {}
template<std::size_t...Is, class Tuple>
static void invoke_impl(F& f, std::index_sequence<Is...>, Tuple&& t)
{
f(std::get<Is>(std::forward<Tuple>(t))...);
}
void invoke(F&& f) const & override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
args_);
/* somehow call f with args_ (something like std::apply) */
}
void invoke(F&& f) && override
{
invoke_impl(f,
std::make_index_sequence<std::tuple_size<tuple_type>::value>(),
std::move(args_));
/* somehow call f with args_ (something like std::apply) */
}
private:
using tuple_type = std::tuple<FunctionArgs...>;
tuple_type args_;
};
template<class Callable, class...MyArgs>
auto later(MyArgs&&...args) {
return Args<Callable, std::decay_t<MyArgs>...>(std::forward<MyArgs>(args)...);
}
void foo(const std::string&, std::string)
{
}
int main()
{
auto l = later<decltype(&foo)>(std::string("hello"), std::string("world"));
l.invoke(foo);
std::move(l).invoke(foo);
}

If you're trying to save a function call with its parameters for later invocation, you could use lambdas packaged in std::function objects:
template<typename F, typename ... Args>
std::function<void()> createInvocation(F f, const Args& ... args)
{
return [f,args...]() { f(args...); };
}
Then you could use it like this:
void myFunc(int a, int b)
{
std::cout << "Invoked: " << a + b << std::endl;
}
int main() {
auto invocation = createInvocation(myFunc, 1, 2);
invocation();
return 0;
}
UPDATE: If you wanted to create a generic non-templated container type, you can wrap a tuple into a type that itself derives from a non-templated type. The main problem then is accessing the underlying data. This can be solved by creating a static function dispatch table that for a given tuple type, redirects queries so that std::get, which requires a compile-time constant index template parameter, can instead be invoked with a dynamically provided function parameter. Here is an implementation that achieves this:
class GenericTupleContainer
{
public:
virtual const void* getItemAtIndex(size_t index) = 0;
};
template<typename ... T>
class TupleContainer : public GenericTupleContainer
{
public:
TupleContainer(T&& ... args)
: data(std::forward<T>(args)...)
{}
const void* getItemAtIndex(size_t index) override
{
if(index >= sizeof...(T))
throw std::runtime_error("Invalid index");
return dispatchTable[index](data);
}
private:
template<size_t index>
static const void* getItemAtIdx(const std::tuple<T...>& data)
{
return &std::get<index>(data);
}
using GetterFn = const void*(*)(const std::tuple<T...>&);
static GetterFn* initDispatchTable()
{
static GetterFn dispatchTable[sizeof...(T)];
populateDispatchTable<sizeof...(T)>(dispatchTable, std::integral_constant<bool, sizeof...(T) == 0>());
return dispatchTable;
}
static GetterFn* dispatchTable;
template<size_t idx>
static void populateDispatchTable(GetterFn* table, std::false_type);
template<size_t idx>
static void populateDispatchTable(GetterFn* table, std::true_type)
{
//terminating call - do nothing
}
std::tuple<T...> data;
};
template<typename ... T>
typename TupleContainer<T...>::GetterFn* TupleContainer<T...>::dispatchTable = TupleContainer<T...>::initDispatchTable();
template<typename ... T>
template<size_t idx>
void TupleContainer<T...>::populateDispatchTable(GetterFn* table, std::false_type)
{
table[idx-1] = &TupleContainer<T...>::template getItemAtIdx<idx-1>;
populateDispatchTable<idx-1>(table, std::integral_constant<bool, idx-1 == 0>() );
}
template<typename ... T>
auto createTupleContainer(T&& ... args)
{
return new TupleContainer<T...>(std::forward<T>(args)...);
}
Then you can use the above as follows:
int main() {
GenericTupleContainer* data = createTupleContainer(1, 2.0, "Hello");
std::cout << *(static_cast<const int*>(data->getItemAtIndex(0))) << std::endl;
std::cout << *(static_cast<const double*>(data->getItemAtIndex(1))) << std::endl;
std::cout << (static_cast<const char*>(data->getItemAtIndex(2))) << std::endl;
return 0;
}
As you can see from the above usage, you've achieved the aim of wrapping an arbitrary templated tuple into a non-templated type, in such a way that you can access the component members with a normal (function) index parameter instead of a template one. Now the return type of such a getter has to be universal, so I've chosen to use void* here, which is not ideal. But you can develop this idea to make this container give more useful information about the types of its data tuple members. Also, note that this does use a virtual function. With some further work you can get rid of this as well, although you won't be able to get rid of at least one function pointer lookup (i.e. the lookup in the dispatch table) - this is the price paid for gaining the flexibility of being able to use a runtime value to index into the tuple.

Related

How to identify if a method of underlying type held by a shared_ptr can be invoked with one or no parameters at compile time

Using C++ 17. I have the following:
template <typename T>
using ptr_t = std::shared_ptr<const T>;
class some_type;
class A { some_type foo() const; }
class B { some_type foo() const; }
class C { some_type foo(int) const; }
std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>>;
A variant holds shared_ptr(s) to different types. All expected to have function foo() that may be void or take a parameter. I will then have a visitor that would correctly dispatch foo, something like this (conceptually):
struct visitor
{
template <typename T>
ptr_t<some_type> operator()(const T& config) const
{
if constexpr (// determine if foo() of the underlying type of a shared_ptr can be called with int param)
return config->foo(15);
else
return config->foo();
}
is there a way to say this? I tried various ways but can't come with something that compiles. Template parameter, T, is ptr_t<A|B|C>.
std::is_invocable_v<Callable, Args...> is the way to go. Unfortunatelly, it will not compile just like that with if constexpr. It will either fail because "there is no operator()() overload", or there is no overload for operator taking Args....
I suggest you add a wrapper class for a callable and use it with a specialized alias template of std::variant instead of writing your own visitor. It will allow you to use std::visit seamlessly.
#include <type_traits>
#include <variant>
template <typename Callable>
class wrapped_callable
{
Callable c;
public:
wrapped_callable(Callable c)
: c(c)
{}
template <typename ... Args>
constexpr decltype(auto) operator()(Args &&... args) const
{
return _invoke(std::is_invocable<Callable, Args...>{}, c, std::forward<Args>(args)...);
}
private:
using _invocable = std::true_type;
using _non_invocable = std::false_type;
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_invocable, const T& t, Args &&... args)
{
return t(std::forward<Args>(args)...);
}
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_non_invocable, const T& t, Args ... args)
{
return t();
}
};
template <typename ... T>
using variant_callable = std::variant<wrapped_callable<T>...>;
struct int_callable
{
int operator()(int i) const
{
return i;
}
};
struct non_callable
{
int operator()() const
{
return 42;
}
};
#include <iostream>
int main()
{
using variant_t = variant_callable<int_callable, non_callable>;
// 23 is ignored, 42 is printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{non_callable()});
// 23 is passed along and printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{int_callable()});
}
Program returned: 0
42
23
https://godbolt.org/z/e6GzvW6n6
But The idea is not to have any specialization for all types in a variant as it will then require changing the visitor code every time a new type is added.
That is what template alias of std::variant<wrapped_callable<T>...> for. You just add append a new type to the list, that's it.
Take notice, that it does not depend on if constexpr. So if you manage to provide your own variant and is_invocable_v, it will work for C++14. For C++11 possibly, but some modifications regarding constexpr functions might be needed.
Of course you can implement your visitor in the same manner if you want to use std::shared_ptr istead of a callable.
But I don't see any reason to use:
visitor + smart pointer. Just use a smart pointer - it will give you runtime polymorphism in a "classic" way (via virtual inheritence)
why std::shared_ptr? Do you really need to share the ownership? Just stick with std::unique_ptr

How to call a generic std::function with a list of void* parameters?

I have a std::map where I store some arbitrary methods that I want to call later.
map<string, function<void(void)>> methods;
template<typename R, typename ...P>
void storeMethod(const string& name, const function<R(P...)>& method) {
methods[name] = method;
}
A the time of calling, I get the parameters to call the method with in a vector<void*>, where the first element is a pointer where I will store the return value.
How do I automatically cast these parameters to the corresponding types of the method I want to call?
Should I store the types in some way maybe?
void callMethod(const string& name, vector<void*> parameters) {
auto method = methods[name];
// How to call 'method' with all the parameters casted to the required types?
}
For example, if I orignally called storeMethod() with a function<int(string a, float b)>, I need a generic way to call it in callMethod() like this:
*((int*)parameters[0]) = method(*((string*)parameters[1]), *((float*)parameters[2]));
You will have to wrap method in something that can remember the parameter types.
struct OpaqueFunction {
virtual std::any call(const std::vector<std::any> &) = 0;
};
template <typename R, typename ... Args>
struct OpaqueFunctionImpl : OpaqueFunction {
OpaqueFunctionImpl(std::function<R(Args...)> f) : f(std::move(f)) {}
std::any call(const std::vector<std::any> & parameters) override {
return call_impl(parameters, std::index_sequence_for<Args...>{});
}
private:
template <size_t... I>
std::any call_impl(const std::vector<std::any> & parameters, std::index_sequence<I...>) {
return f(std::any_cast<Args>(parameters.at(I))...);
}
std::function<R(Args...)> f;
};
class Methods {
std::map<std::string, std::unique_ptr<OpaqueFunction>> methods;
public:
template<typename R, typename ... Args>
void storeMethod(std::string name, std::function<R(Args...)> method) {
methods[std::move(name)] = std::make_unique<OpaqueFunctionImpl<R, Args...>>(std::move(method));
}
template<typename R>
R callMethod(const std::string & name, const std::vector<std::any> & parameters) {
return std::any_cast<R>(methods.at(name)->call(parameters));
}
};
You can create a Callable type to functions that take different types of arguments and then, store that in a vector (using vector here for simplicity):
struct Callable {
Callable(std::function<void()> f) : zero_(std::move(f)) {}
Callable(std::function<void(int)> f) : one_(std::move(f)) {}
void operator()() { zero_(); }
void operator()(int x) { one_(x); }
std::function<void()> zero_;
std::function<void(int)> one_;
};
//vector of methods
std::vector<Callable> methods;
To store a method, you can either use a template-ized function or just use overloads. I am using overloads here:
void addMethod(std::function<void()> func)
{
methods.push_back(Callable(func));
}
void addMethod(std::function<void(int)> func)
{
methods.push_back(Callable(func));
}
And then to finally call a function:
template<typename ...Args>
void callMethod(int idx, Args ...args) {
auto method = methods[idx];
method(std::forward<Args>(args)...);
}
Main:
int main()
{
addMethod([](int x){
std::cout << "I am function(int)" << x << '\n';
});
addMethod([](){
std::cout << "I am just function()\n";
});
callMethod(0, 200);
callMethod(1);
}
This is the simplest possible way I can think of to achieve this. Their might be better ways and I am really curious about them.
Try it out here: https://godbolt.org/z/HS5a7p

Passing member function pointer as template parameter

I want to create a wrapper class which is able to call member functions (of any type) of the wrapped class with help of templates. This is what I have so far:
template <typename T>
class wrapper {
public:
template<typename R, R (T::*func)()>
void call_func() {
(wrapped.*func)();
}
private:
T wrapped;
};
class some_class {
private:
int i = 2;
public:
void some_func() {
std::cout << i << std::endl;
}
};
int main() {
wrapper<some_class> wr;
// How I need to call at the moment:
wr.call_func<void, &some_class::some_func>();
// How I want call:
wr.call_func<&some_class::some_func>();
return 0;
}
As you can see in the comments of the main function, I want to call the wrapper-function without explicitly specifying the return type of the wrapped member function. (How) Can this be done in C++11?
template<typename F>
void call_func(F func) {
(wrapped.*func)();
}
then call like this:
wr.call_func(&some_class::some_func);
If you want to use the return value too, you'll need this:
template<typename F>
auto call_func(F func) -> decltype((std::declval<T>().*func)()) {
return (wrapped.*func)();
}
If you have C++14, you can omit the -> decltype(...) part and use decltype(auto) as the return value.
If you also want to pass functions, you can use variadic templates and forwarding for that.
template<typename F, typename... Args>
decltype(auto) call_func(F func, Args&&... args) {
return (wrapped.*func)(std::forward<Args>(args)...);
}
You can directly use std::function
For more information on std::function see: http://en.cppreference.com/w/cpp/utility/functional/function

C++11 std::conditional at runtime?

I'm looking to do something like this:
void func(void *data, const int dtype)
{
typedef typename std::conditional<dtype==0,float,double>::type DataType;
funcT((DataType *)data);
return;
}
This will not compile because dtype needs to be known at compile time. I'm trying to avoid using a switch statement, because I have 8 data types I am working with, with many functions such as the one above, being called from Python via ctypes.
Is there a way something like std::conditional can done during run time, making use of the dtype identifier passed in?
All types must be resolved at compile time. So no type, can ever depend on a runtime parameter to a function. The way to handle something like this is basically to build a visiting mechanism, once, and then you can reuse it. Basically, something like this:
template <class F>
void visit_data(void* data, const int dtype, F f) {
switch (dtype)
case 0: f(*static_cast<float*>(data));
case 1: f(*static_cast<double*>(data));
}
Now you can implement functions by writing visitors:
struct func_impl {
void operator()(float&) { ... }
void operator()(double&) { ... }
};
Your visitor can also use generic code:
struct func_impl2 {
template <class T>
void operator()(T&) { ... }
};
Then you can write your function by leveraging the visitor:
void func(void* data, const int dtype) {
visit_data(data, dtype, func_impl{});
}
The switch case over your list of types will only appear once in your entire codebase. If you add a new type, any visitor that doesn't handle it will give a compile time error if used.
You can also use lambdas to do it inline with a helper function or two; especially useful in 14 where you have generic lambdas.
If you can use C++17 it can be solved with a std::visitor and std::variant like so:
using var_t = std::variant<float, double>;
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
void func(var_t arg) {
std::visit(overloaded {
[](float arg) { foo_float(arg); },
[](double arg) { foo_double(arg); },
}, arg);
}
I'll start with a c++14 answer then detail how to downgrade c++11.
Suppose you have a list of types:
template<class...>
struct types{using type=types;};
const types<int, double, char> supported_types;
Next we write some utility functions
template<std::size_t I, class...Ts>
using get_type = std::decay_t<decltype(std::get<I>(std::declval<std::tuple<Ts...>&>()))>;
template<std::size_t I, class Types>
struct type_at_helper;
template<std::size_t I, class...Ts>
struct type_at_helper<I, types<Ts...>>{
using type=get_type<I,Ts...>;
};
template<std::size_t I, class Types>
using type_at = typename type_at_helper<I,Types>::type;
Now, type_at<2, decltype(supperted_types)> is char.
namespace helper {
template<class F>
using invoker = void(*)(F&&, void*);
template<class F, class Types, std::size_t I>
invoker<F> get_invoker() {
return [](F&& f, void* pdata) {
std::forward<F>(f)( static_cast<type_at<I, Types>*>(pdata) );
};
}
template<class F, class Types, std::size_t...Is>
void dispatch( F&& f, void* data, unsigned type_index, std::index_sequence<Is...>, Types ={} ) {
using pF=std::decay_t<F>*;
using invoker = void(*)(pF, void*);
static const invoker table[]={
get_invoker<F, Types, Is>()...
};
table[type_index]( std::forward<F>(f), data );
}
}
template<class F, class...Ts>
void dispatch( F&& f, void* data, unsigned type_index, types<Ts...> {} ) {
details::dispatch( std::forward<F>(f), data, type_index, std::make_index_sequence<sizeof...(Ts)>{}, types<Ts...>{} );
}
and done.
The downgrade to c++11 simply write make_index_sequence and index_sequence. Here is a high quality one, but there are easier ones out there.
Is there a way something like std::conditional can done during run time, making use of the dtype identifier passed in?
No, there isn't. A run time value cannot be used to make type based decisions at compile type.
Given your post, the simplest solution is to use an if statement.
void func(void *data, const int dtype)
{
if ( dtype == 0 )
{
funcT(static_cast<float*>(data));
}
else
{
funcT(static_cast<double*>(data));
}
}
To be able to deal with lots of such functions, I would recommend using std::map<int, std::function<void(void*)>>.
Here's a simple program that compiles and builds for me.
#include <map>
#include <functional>
void funcT(float* data)
{
}
void funcT(double* data)
{
}
struct MyType {};
void funcT(MyType* data)
{
}
void func(void *data, const int dtype)
{
std::map<int, std::function<void(void*)>> functions =
{
{0, [](void* in) {funcT(static_cast<float*>(in));}},
{1, [](void* in) {funcT(static_cast<double*>(in));}},
// ...
{7, [](void* in) {funcT(static_cast<MyType*>(in));}}
};
if ( functions[dtype] != nullptr )
{
functions[dtype](data);
}
}
int main(){}
One advantage of using the lambda functions is that you are free to call differently named functions for the various types. For example, you have option of using:
void foo(MyType* data) {}
and
{7, [](void* in) {foo(static_cast<MyType*>(in));}}
My solution to the problem would be a generic selectFunc() function which would select a function from a provided function set FS based on dtype, and return it:
using FuncType = void(*)(void*);
template<typename FS>
FuncType selectFunc(int dtype);
The function set would be a class with static handle() methods which would accept different types and a static fallback() method which would be called if dtype is not valid.
Example Usage:
struct FuncSet
{
static void fallback() {};
static void handle(float*) {};
static void handle(double*) {};
};
void func(void *data, int dtype)
{
// select a function from FuncSet based on dtype:
auto f = selectFunc<FuncSet>(dtype);
// invoke the selected function with the provided data:
f(data);
// note, two lines above could be combined into one line
}
Implementation:
// Static method which would call the correct FS::handle() method
template<typename FS, typename T>
struct Helper
{
static void dispatch(void *data) { FS::handle(static_cast<T*>(data)); }
};
// Static method which would call FS::fallback()
template<typename FS>
struct Helper<FS, void>
{
static void dispatch(void*) { FS::fallback(); }
};
template<typename FS>
FuncType selectFunc(int dtype)
{
switch ( dtype ) {
case 0: return &Helper<FS, float>::dispatch;
case 1: return &Helper<FS, double>::dispatch;
// ... add other types here ...
default: return &Helper<FS, void>::dispatch; // call fallback()
}
}

lazy initialization with forwarding

Take a "lazy" constructor that might have the following interface:
template<class T>
struct LazyConstruct {
// accept any number of arguments,
// which would later be used to construct T
template<class... U>
LazyConstruct(U&&... u) {
// store the arguments somehow
}
T& get() {
if(!data) data.reset( new T( /* unpack the arguments */ ) );
return *data;
}
private:
std::unique_ptr<T> data;
};
What would be a nice way to implement this?
Here's a little bit of a convoluted way of doing what you want. The basic idea is to have LazyConstruct store the arguments pack in a tuple, and then unpack the tuple on demand to construct 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;
};
I'm making use of C++14's std::index_sequence, if your standard library implementation does not ship this, then there are several examples on SO (this or this) showing how it can be implemented.
Finally a helper function template to construct LazyConstruct instances
template<class T, class... Args>
LazyConstruct<T, Args...> make_LazyConstruct(Args&&... args)
{
return LazyConstruct<T, Args...>{std::forward<Args>(args)...};
}
Live demo
Another version based on Alf's answer that uses std::function so that LazyConstruct's type doesn't change based on T's constructor signature.
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
I am not sure about your question, but for lazy initialization I suggest you to use something along the lines of boost::optional<T>. You can delay initialization with it and you will not make use of a pointer and heap memory.
class MyClass {
public:
void f();
};
void anotherFunc(MyClass & c);
boost::optional<MyClass> mc; //Not initialized, empty, stack memory.
mc = MyClass{};
if (mc != boost::none)
mc->f();
anotherFunc(*mc);
Documentation is here: Boost.Optional
The easiest is probably to just capture the arguments in a lambda.
template<class T>
struct LazyConstruct {
// accept any number of arguments,
// which would later be used to construct T
template<class... U>
LazyConstruct(U&&... u)
: create( [=]() -> T* { return new T(u...); } )
{}
T& get() {
if(!data) data.reset( data.reset( create() ) );
return *data;
}
private:
std::unique_ptr<T> data;
std::function<auto()->T*> create;
};
Disclaimer: Code not touched by compiler's hands.
Note: While I'm unable right now to say exactly what's wrong with the idea (it's pretty late), lazy creation doesn't smell right, somehow. I suspect premature optimization.
As per the comment before. You want to delay and capture the arguments.
EDIT: Generalized solution, should work in C++11. Warnings: not tested. apply function is left as an exercise. See here for a possible implementation:
template <class T>
struct make {
template <class...Args>
T operator()(Args &&... args) const {
return T(std::forward<Args>(args)...);
}
};
template <class T, class... Args>
struct object_builder {
object_builder(Args... && args) :
captured_args_(std::forward<Args>(args)...) {}
T operator()() const {
return apply(make<T>{},
captured_args_);
}
private:
std::tuple<Args...> captured_args_;
};
template <class T, class...Args>
object_builder<T, Args...> make_object_builder(Args &&...args) {
return object_builder<T, Args...>(std::forward<Args>(args)...);
}
int main() {
//Create builders with captured arguments
auto scary_monster_builder =
make_object_builder<Monster>(scary, "big orc");
auto easy_monster_builder = make_object_builder<Monster>(easy,
"small orc");
//Instantiate objects with the captured arguments from before
auto a_scary_monster = scary_monster_builder();
auto an_easy_monster = easy_monster_builder();
}