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.
Related
I tried finding this one but couldn't. I am new to C++ template programming. I have a situation like this -:
#include <bits/stdc++.h>
enum DataType{
FLOAT32,
SIGNED32
:,
: (there can be other dataTypes as well)
};
struct SomeClass{
DataType d;
void* pointer;
};
void add(SomeClass a, SomeClass b)
{
DataType dataType = a.d;
using aDataType = std::conditional<dataType == FLOAT32 , float, int>;
}
int main()
{
SomeClass a;
a.d = FLOAT32;
SomeClass b;
b.d = SIGNED32;
int* p = static_cast<int*>(malloc(sizeof(int)));
*p = 4;
b.pointer = p;
float* p2 = static_cast<float*>(malloc(sizeof(float)));
*p2 = 4.3;
a.pointer = p2;
add(a, b);
return 0;
}
I want to find out the datatype of what's stored in a.pointer and b.pointer but this is giving a compile-error, saying the value of ‘dataType’ is not usable in a constant expression.
You can't use operator==, since the dataType is only known at runtime. What you are basically trying to do here is to mimic C-unions, which are quite unrelated to templates. Note, that once you receive SomeClass as a parameter, you can't really distinguish between the underlying types on compile time.
I would suggest this code:
#include <bits/stdc++.h>
template<typename T, typename U>
void add(T* a, U* b)
{
using aDataType = T; // Unnecessary, but for the example
}
int main()
{
int i = 4;
float f = 4.3;
add(&i, &f);
return 0;
}
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.
This question already has answers here:
Iterating over a struct in C++
(8 answers)
Closed 1 year ago.
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
No, it's not possible, because there is no reflection in C++.
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance.members[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
};
std::array<double, 3> components;
};
};
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
for (double component : point.components)
{
// do something
}
Assuming that all class members are of the same type, you may employ a C++17 feature called structured binding. Assuming that all members are public this would work:
struct SI
{
int x;
int y;
int z;
};
struct SD
{
double x;
double y;
double z;
};
template<typename T>
void print(const T &val)
{
const auto& [a, b, c] = val;
for (auto elem : {a, b, c})
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
This would work with any struct that has exactly 3 public elements of the same (copyable) type. In case of non-public members the function must be a friend or a member. This approach however cannot be easily extented to arbitrary number of elements.
This is an improved version of QCTDevs answer:
class MyClass
{
union
{
struct Memberstruct
{
double test0;
double test1;
double test2;
} m;
array<double, sizeof( Memberstruct ) / sizeof( double )> memberarray;
};
bool test() { &(m.test1) == &(memberarray[1]); }
};
The requirement is still to have all the same datatypes, and you also need to implement the default Constructor, if needed.
It is improved in that you don't need to manually maintain the size of the array.
A drawback is an altered syntax in comparison to the class without this workaround.
Is it possible to declare a template without parameters?
I have a template like:
template < int i, int j>
class X{
int doSomething() { return i+j;}
}
and now i want to use this Template in another class, but i don't know its parameter cause they are variable. But i would like to save different templates in a variable like this :
class Foo {
X var;
void setVar ( const X &newVar) { var = newVar; }
X getVar () { return var;}
}
Is there a way to save different types of the template in one variable ? or pointer ?
Thx for help
Templates are resolved at compile time; your template parameters can't depend on values that aren't known until runtime. Furthermore, each instance of a template is a different type: X<1, 2> and X<3, 4> are different just like two classes Foo and Bar are different; a variable of the one type can't hold a value of the other. You can't have a variable whose type is just X, because X is not a type (it's a template).
It doesn't make sense for a template to have no parameters; you don't need a template at all in that case. It's not clear why you're trying to use templates to add two variables. You probably want to just use a class that holds two integers passed to its constructor:
class X {
private:
int i, j;
public:
X(int i, int j): i(i), j(j) { }
int doSomething() const { return i + j; }
};
This will let you have variables of type X, and you can construct different instances of X with different values for i and j based on variables at runtime.
You would want to use type erasure. boost::any provides a good implementation which might suffice for your use case. Here's the example from there modified for your situation :
BOOST_TYPE_ERASURE_MEMBER((canDoSomething), doSomething, 0)
class Foo {
using X = any<canDoSomething<int(void)>>;
X var;
void setVar ( const X &newVar) { var = newVar; }
X getVar () { return var;}
int DoSomethingWithX() { return var.doSomething();}
}
This question already has answers here:
Iterating over a struct in C++
(8 answers)
Closed 1 year ago.
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
You can use the REFLECTABLE macro given in this answer to define the struct like this:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
struct print_visitor
{
template<class FieldData>
void operator()(FieldData f)
{
std::cout << f.name() << "=" << f.get() << std::endl;
}
};
template<class T>
void print_fields(T & x)
{
visit_each(x, print_visitor());
}
A x;
print_fields(x);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
struct print_visitor
{
template<class Index, class C>
void operator()(Index, C & c)
{
std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call()
<< "="
<< boost:::fusion::at<Index>(c)
<< std::endl;
}
};
template<class C>
void print_fields(C & c)
{
typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
No, it's not possible, because there is no reflection in C++.
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance.members[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
};
std::array<double, 3> components;
};
};
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
for (double component : point.components)
{
// do something
}
Assuming that all class members are of the same type, you may employ a C++17 feature called structured binding. Assuming that all members are public this would work:
struct SI
{
int x;
int y;
int z;
};
struct SD
{
double x;
double y;
double z;
};
template<typename T>
void print(const T &val)
{
const auto& [a, b, c] = val;
for (auto elem : {a, b, c})
{
std::cout << elem << " ";
}
std::cout << std::endl;
}
This would work with any struct that has exactly 3 public elements of the same (copyable) type. In case of non-public members the function must be a friend or a member. This approach however cannot be easily extented to arbitrary number of elements.
This is an improved version of QCTDevs answer:
class MyClass
{
union
{
struct Memberstruct
{
double test0;
double test1;
double test2;
} m;
array<double, sizeof( Memberstruct ) / sizeof( double )> memberarray;
};
bool test() { &(m.test1) == &(memberarray[1]); }
};
The requirement is still to have all the same datatypes, and you also need to implement the default Constructor, if needed.
It is improved in that you don't need to manually maintain the size of the array.
A drawback is an altered syntax in comparison to the class without this workaround.