Passing value in factory pattern - c++

I am learning factory design pattern. I am not able to figure out how we can pass parameters to object created using Factory pattern.
One Small Silly Example:
Suppose I have three class, Class A and class B and Class Number. Number being the base class. Also, class A expects three integers and has functionality to add them and class B expects two integer and adds them
Code Snippet:
int main()
{
Factory *facObj = new Factory();
// Addition for Two Integers
Number * numberObjOne = facObj->createObj("AddThreeInteger");
Number * numberObjTwo = facObj->createObj("AddTwoInteger");
}
Factory.cpp
Number * Factory::createObj(string str)
{
if (str == "AddThreeInteger")
{
return new A(1,2,3);
}
else if (str == "AddTwoInteger")
{
return new B(1,2);
}
else
return NULL;
}
Question: Now no matter what I do I can only add the hard coded numbers. How do I pass these integers value from my Client code or from main(). Its a silly example and I am new to programming. Kindly help me here. How can I not hardcode the value and get the results. Can I somwhow pass the values at facObj->createObj Am I making sense? Kindly help me.

Complete, runnable example. c++11 or better.
Note the use of unique_ptr. Don't use raw pointers.
#include <iostream>
#include <memory>
#include <stdexcept>
#include <exception>
#include <utility>
template<class T, class...Args>
struct creatable_from {
template<class X, class...Ys>
static auto test(int) -> decltype(X(std::declval<Ys>()...), void(), std::true_type());
template<class X, class...Ys>
static auto test(...) -> decltype(std::false_type());
static constexpr auto value = decltype(test<T, Args...>(0))::value;
};
struct Operation {
virtual ~Operation() = default;
virtual int operator()() const = 0;
};
struct Add : Operation
{
Add(int x, int y)
: x(x), y(y)
{}
int operator()() const override {
return x + y;
}
int x, y;
};
struct Sub : Operation
{
Sub(int x, int y)
: x(x), y(y)
{}
int operator()() const override {
return x - y;
}
int x, y;
};
struct AddSub : Operation
{
AddSub(int x, int y, int z)
: x(x), y(y), z(z)
{}
int operator()() const override {
return x + y - z;
}
int x, y, z;
};
struct Factory
{
template<class...Args>
std::unique_ptr<Operation> create(const std::string& type, Args&&...args)
{
if (type == "Add") {
return do_create<Add>(std::forward<Args>(args)...);
}
if (type == "Sub") {
return do_create<Sub>(std::forward<Args>(args)...);
}
if (type == "AddSub") {
return do_create<AddSub>(std::forward<Args>(args)...);
}
// default - return a null pointer, but would probably be better to
// throw a logic_error
return {};
}
private:
template<class T, class...Args>
static auto do_create(Args&&...args)
-> std::enable_if_t< creatable_from<T, Args...>::value, std::unique_ptr<T> >
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
template<class T, class...Args>
static auto do_create(Args&&...args)
-> std::enable_if_t< not creatable_from<T, Args...>::value, std::unique_ptr<T> >
{
throw std::invalid_argument("wrong number of arguments");
}
};
int main()
{
auto facObj = Factory();
auto t1 = facObj.create("Add", 2, 3);
auto t2 = facObj.create("Sub", 3, 2);
auto t3 = facObj.create("AddSub", 2, 3, 4);
std::cout << (*t1)() << std::endl;
std::cout << (*t2)() << std::endl;
std::cout << (*t3)() << std::endl;
}
expected output:
5
1
1

There are many ways to do it.
One way is to have separate create methods in your factory, to construct each one of your subclasses. Each create method would take the appropriate parameters for the subclass it constructs, and forwards them to the subclass's constructor, accordingly.
Another way is to have a separate "parameters" class that would define, in some way, the parameters for the created object. It would allow those parameters to be specified. For this case, a std::vector would be appopriate. Then, your create() method would have to validate that the passed parameters are valid, and throw an exception otherwise, or something along the same lines.

I am not an expert on design patterns. So I am not sure if the following suggestions are still compatible with the factory pattern.
One way could be to create different methods like CreateObjectA(int a, int b, int c) and CreateObjectB(int a, int b). Another option could be to add a std::vector<int> to your method createObj. If all classes A, B, ... differ in the number of integers, the length of the vector could be used to decide which object to create. If this is not possible you could e.g. use some sort of ID to tell the factory which object to create.

Option 1
You could generalize your factory class using templates.
For instance, you could send the type you want to construct to the factory.
This is an example for what could be possible solution for your case:
struct Factory {
template<typename T, typename... Args>
T create(Args&&... args) {
return T{1, 2, std::forward<Args>(args)...};
}
};
It will be used like this:
Factory factory;
auto myA = factory.create<A>(1, 2, "an additional char* parameter");
// no additional parameter works too
auto myB = factory.create<B>();
Well, this class is pretty simple. It construct a type T with the arguments Args, plus two int parameter. But it will not allow making a different type depending on the value of a string though.
Btw you should replace every new in your code by std::make_unique, there where a lot of memory leaks in your code. Alternatively, you can create objects of the stack.
Option 2
If you know what type to construct depending on the parameters you send, you could just overload your function.
Here's what it would look like:
struct Factory {
A create(int a, int b, int c) {
return A{a, b, c};
}
B create(int a, int b) {
return B{a, b};
}
};
You could use it like this:
Factory factory;
auto myA = factory.create(1, 2, 3);
auto myB = factory.create(1, 2);
This might be easier to implement. But take note that you will not be able to have a class with two constructor neither you won't be able to have two class with the same parameters.

Related

Walk over variants that share the same member and get it?

In the example below, is it possible to create a function getX that walks over the variant cases and get the x variable?
#include <variant>
class A {
int x = 0;
};
class B {
int x = 1;
};
class C {
int x = 1;
};
std::variant<A, B, C> variant;
One obvious solution would be:
int getX(std::variant<A, B, C>& variant) {
if (std::holds_alternative<A>(variant)) {
} else //...
}
but then every time I add a new variant it'd be tedious to write code that treats the new case.
Is there a more automated, perhaps constexpr way of doing this? I think it's even possible to do for different variable names in each class. The one call that works should be the chosen one for the class.
That's a "visit". You can do this:
#include <variant>
struct A {
int x = 0;
};
struct B {
int x = 1;
};
struct C {
int x = 1;
};
std::variant<A, B, C> var = A{};
int main() {
int n = std::visit([](auto & obj) {return obj.x;}, var);
}
Note, passing visit a generic lambda (taking an auto parameter) is actually a template, so whatever type is in the variant, that's the type of reference obj will be. I had to change your classes to structs so that the data was accessible.

How to get function pointer from many functions and pass args to it?

I have many defined functions as follows, all return an int
int fn1(int x) {
return x;
}
int fn2(std::string x, int y, std::string z) {
// process string x and z
int x1 = process(x);
int z1 = process(z);
return x1 + y + z1;
}
// ... and many more similar functions
For some reasons, I need to implement a wrapper to call the above functions by function names,
int wrapper(std::string fn_name, some_struct_t data, std::vector<std::string> field_names) {
a_fn_ptr_type fn_ptr = nullptr; // <q1>: is this a right way to do?
// by fn_name, decide which fn to call
if (fn_name == "fn1") {
fn_ptr = &fn1;
}
if (fn_name == "fn2") {
fn_ptr = &fn2;
}
...
// given field_names, get the field from data, pass them to fn_ptr as args
for (auto field_name: field_names) {
std::any value = get_from_data(data, field_name, field_type); // field_type will be updated by this call, so that we know the value type.
// <q2>: but how to pass each value as arg to fn_ptr here?
}
}
The above code demonstrate what I want to achieve, and I have 2 questions (as pointed by <q1> and <q2>).
I'm not sure if the code is the right way to go, hope to get some advice from people, thanks!
Inspired by the comments:
A wrapper that takes some_struct_t data, std::vector<std::string> field_names. Assuming a
template <typename T>
T get_from_data(some_struct_t, std::string);
You have a function type
using func_t = std::function<int(const some_struct_t &, const std::vector<std::string>&)>;
which you can instantiate from functions via
template <typename... Args, size_t... Is>
auto wrap_impl(int(*func)(Args...), std::index_sequence<Is...>)
{
return [func](const some_struct_t & data, const std::vector<std::string>& field_names)
{ return func(get_from_data<Args>(data, field_names.at(Is))...); };
}
template <typename... Args>
func_t wrap(int(*func)(Args...))
{
return wrap_impl(func, std::index_sequence_for<Args...>{});
}
and then you can have a
std::map<std::string, func_t> functions;

Virtually turn vector of struct into vector of struct members

I have a function that takes a vector-like input. To simplify things, let's use this print_in_order function:
#include <iostream>
#include <vector>
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<int> printme = {100, 200, 300};
std::vector<int> order = {2,0,1};
print_in_order(order, printme);
}
Now I have a vector<Elem> and want to print a single integer member, Elem.a, for each Elem in the vector. I could do this by creating a new vector<int> (copying a for all Elems) and pass this to the print function - however, I feel like there must be a way to pass a "virtual" vector that, when operator[] is used on it, returns this only the member a. Note that I don't want to change the print_in_order function to access the member, it should remain general.
Is this possible, maybe with a lambda expression?
Full code below.
#include <iostream>
#include <vector>
struct Elem {
int a,b;
Elem(int a, int b) : a(a),b(b) {}
};
template <typename vectorlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme) {
for (int i : order)
std::cout << printme[i] << std::endl;
}
int main() {
std::vector<Elem> printme = {Elem(1,100), Elem(2,200), Elem(3,300)};
std::vector<int> order = {2,0,1};
// how to do this?
virtual_vector X(printme) // behaves like a std::vector<Elem.a>
print_in_order(order, X);
}
It's not really possible to directly do what you want. Instead you might want to take a hint from the standard algorithm library, for example std::for_each where you take an extra argument that is a function-like object that you call for each element. Then you could easily pass a lambda function that prints only the wanted element.
Perhaps something like
template<typename vectorlike, typename functionlike>
void print_in_order(std::vector<int> const & order,
vectorlike const & printme,
functionlike func) {
for (int i : order)
func(printme[i]);
}
Then call it like
print_in_order(order, printme, [](Elem const& elem) {
std::cout << elem.a;
});
Since C++ have function overloading you can still keep the old print_in_order function for plain vectors.
Using member pointers you can implement a proxy type that will allow you view a container of objects by substituting each object by one of it's members (see pointer to data member) or by one of it's getters (see pointer to member function). The first solution addresses only data members, the second accounts for both.
The container will necessarily need to know which container to use and which member to map, which will be provided at construction. The type of a pointer to member depends on the type of that member so it will have to be considered as an additional template argument.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
private:
const Container * m_container;
MemberPtr m_member;
};
Next, implement the operator[] operator, since you mentioned that it's how you wanted to access your elements. The syntax for dereferencing a member pointer can be surprising at first.
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// Dispatch to the right get method
auto operator[](const size_t p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To use this implementation, you would write something like this :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
virtual_vector<decltype(printme), decltype(&Elem::a)> X(printme, &Elem::a);
print_in_order(order, X);
}
This is a bit cumbersome since there is no template argument deduction happening. So lets add a free function to deduce the template arguments.
template<class Container, class MemberPtr>
virtual_vector<Container, MemberPtr>
make_virtual_vector(const Container & p_container, MemberPtr p_member_ptr)
{
return{ p_container, p_member_ptr };
}
The usage becomes :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
If you want to support member functions, it's a little bit more complicated. First, the syntax to dereference a data member pointer is slightly different from calling a function member pointer. You have to implement two versions of the operator[] and enable the correct one based on the member pointer type. Luckily the standard provides std::enable_if and std::is_member_function_pointer (both in the <type_trait> header) which allow us to do just that. The member function pointer requires you to specify the arguments to pass to the function (non in this case) and an extra set of parentheses around the expression that would evaluate to the function to call (everything before the list of arguments).
template<class Container, class MemberPtr>
class virtual_vector
{
public:
virtual_vector(const Container & p_container, MemberPtr p_member_ptr) :
m_container(&p_container),
m_member(p_member_ptr)
{}
// For mapping to a method
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == true, const size_t> p_index) const
{
return ((*m_container)[p_index].*m_member)();
}
// For mapping to a member
template<class T = MemberPtr>
auto operator[](std::enable_if_t<std::is_member_function_pointer<T>::value == false, const size_t> p_index) const
{
return (*m_container)[p_index].*m_member;
}
private:
const Container * m_container;
MemberPtr m_member;
};
To test this, I've added a getter to the Elem class, for illustrative purposes.
struct Elem {
int a, b;
int foo() const { return a; }
Elem(int a, int b) : a(a), b(b) {}
};
And here is how it would be used :
int main() {
std::vector<Elem> printme = { Elem(1,100), Elem(2,200), Elem(3,300) };
std::vector<int> order = { 2,0,1 };
{ // print member
auto X = make_virtual_vector(printme, &Elem::a);
print_in_order(order, X);
}
{ // print method
auto X = make_virtual_vector(printme, &Elem::foo);
print_in_order(order, X);
}
}
You've got a choice of two data structures
struct Employee
{
std::string name;
double salary;
long payrollid;
};
std::vector<Employee> employees;
Or alternatively
struct Employees
{
std::vector<std::string> names;
std::vector<double> salaries;
std::vector<long> payrollids;
};
C++ is designed with the first option as the default. Other languages such as Javascript tend to encourage the second option.
If you want to find mean salary, option 2 is more convenient. If you want to sort the employees by salary, option 1 is easier to work with.
However you can use lamdas to partially interconvert between the two. The lambda is a trivial little function which takes an Employee and returns a salary for him - so effectively providing a flat vector of doubles we can take the mean of - or takes an index and an Employees and returns an employee, doing a little bit of trivial data reformatting.
template<class F>
struct index_fake_t{
F f;
decltype(auto) operator[](std::size_t i)const{
return f(i);
}
};
template<class F>
index_fake_t<F> index_fake( F f ){
return{std::move(f)};
}
template<class F>
auto reindexer(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return v[f(i)];
});
};
}
template<class F>
auto indexer_mapper(F f){
return [f=std::move(f)](auto&& v)mutable{
return index_fake([f=std::move(f),&v](auto i)->decltype(auto){
return f(v[i]);
});
};
}
Now, print in order can be rewritten as:
template <typename vectorlike>
void print(vectorlike const & printme) {
for (auto&& x:printme)
std::cout << x << std::endl;
}
template <typename vectorlike>
void print_in_order(std::vector<int> const& reorder, vectorlike const & printme) {
print(reindexer([&](auto i){return reorder[i];})(printme));
}
and printing .a as:
print_in_order( reorder, indexer_mapper([](auto&&x){return x.a;})(printme) );
there may be some typos.

Template Class With Variadic Constructor implemented in different ways: What are the benefits and downfalls of each version?

I have this template class written in two different ways: one uses a variadic constructor and the other uses std::initializer_list<T>. For the purpose of this question I will name the classe's differently, but mind you in my project it is the same class as both versions do the same thing. I would like to know what is the benefits and downfalls of both versions. Which one is more efficient and why?
Variadic Version:
#include <vector>
#include <memory>
template<typename T>
class Nodes {
private:
unsigned m_numParams;
std::vector<std::shared_ptr<T>> m_vNodes;
public:
Nodes() : m_numParams(0), m_vNodes { nullptr } {}
template <typename ... Ts >
explicit Nodes( Ts&&...ts ) :
m_numParams( sizeof...(Ts) ),
m_vNodes{ std::make_shared<T>( std::forward<Ts>( ts ) )... }
{}
}; // Nodes
int main() {
int x = 3;
int y = 5;
int z = 7;
Nodes<int> nodes( x, y, z );
return 0;
}
std::initializer_list<T> version
#include <vector>
#include <memory>
template<typename T>
class Nodes2 {
private:
unsigned m_numParams;
std::vector<std::shared_ptr<T>> m_vNodes;
public:
Nodes2() : m_numParams(0), m_vNodes{ nullptr } {}
explicit Nodes2( std::initializer_list<T> ini ) :
m_numParams( ini.size() ) {
for ( auto&& e : ini ) {
m_vNodes.push_back( std::make_shared<T>( e ) );
}
}
}; // Nodes2
int main() {
int x = 3;
int y = 3;
int z = 3;
std::initialize_list<int> ini{ x, y, z };
Nodes2<int> nodes2( ini );
return 0;
}
If you're creating a generic container, and don't know the type of object which will be stored (T), and you want to allow move-construction, then the variadic version is better.
This is because you can't move from an std::initializer_list, so your 2nd version will have to copy construct the T object.
From cppreference:
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T
There is no way to get mutable access to the stored array of objects.

Constructor taking shared_ptr

I have situation like this
struct Foo
{
Foo(int x, int y) : x(x), y(y)
{
}
int x, y;
};
class Bar
{
public:
typedef std::shared_ptr<const Foo> ConstFooPtr;
typedef std::shared_ptr<Foo> FooPtr;
Bar(int index = 0, FooPtr ptr = FooPtr()) : index_(index), ptr_(ptr)
{
}
private:
ConstFooPtr ptr_;
int index_;
};
I want to produce Bar and 2 methods comes to my mind
Bar::FooPtr ptr(new Foo(1, 2)); //1
auto ptr2 = std::make_shared<Bar::FooPtr::element_type>(42, 13); //2
auto bar = Bar(0, ptr);
The first one is pretty general, because if I will change the type of FooPtr perhaps I will not have to chage this code. But it uses new which is bad I guess.
Second doesn't use new, but it assumes that it is shared_ptr which is not general also.
Is there any method to make it work and be general? Or maybe I should never take some ptrs in constructor?
(I store ptr to const Foo because I will make copies of Bar and change index_, but data in ptr_ will be the same - You can assume that Foo is something big with some containers)
Just roll your own version of make_shared and put it as a static member of Bar:
template<typename... Args>
static FooPtr make_shared_foo(Args... args)
{
return ::std::make_shared<Foo>(::std::forward<Args>(args)...);
}
This way you can make you pointer like so:
auto ptr3 = Bar::make_shared_foo(3,14159);
Of course, nothing prevents you from taking this to its ultimate version:
Bar(int index = 0) : index_(index), ptr_(FooPtr())
{ }
template<typename... Args>
Bar(int index, Args... args)
: index_(index)
, ptr_(new Foo(::std::forward<Args>(args)...))
{ }
Which just allows you to pass your arguments to the constructor to Bar which will then forward them to create a pointer to Foo for its own consumption.