creating an object from templates in c++ - c++

I have these structs.
struct V
{
int data[2];
V(int a,int b)
{
data[0] = a;
data[1] = b;
}
}
typedef std::vector<int> X;
struct A
{
B<V> member1;
B<X> member2;
A(V member1_, X member2_) : member1(member1_),member2(member2_){}
}
template<typename T>
struct B
{
T data;
B(T data_){data = data_;}
}
How do I create an object of struct A? I wish to declare an object A like so
A a;
and then use it later to assign member1 to it. This is because I would not know B's data until later in the program run. But the compiler would not let me and complains about default constructor in B, saying I don't have one. How do I write default constructors for B and A then while B is a template? Is there a better way to achieve this?
Thanks for your help.

Give struct B an empty default constructor. It will run the default constructor of data, too. You just need to make sure that T has a default constructor, too (actually, the current code of yours requires that, too - members are constructed before opening brace of constructor).

Related

Is there a cleaner way to define my copy ctor with a mutex?

I have a POD struct like so
struct foo {
std::mutex m_foo_mutex;
int a;
int b;
int c;
//......
};
It has more fields than this but the structure should be apparent. The default copy ctor is, of course, ill formed because std::mutex's copy ctor is delete.
It's perfectly fine for my uses to copy this object, and give the copied object a new mutex. So I have defined something like this inside foo.
foo(const foo &foo2) : m_foo_mutex() {
a = foo2.a;
b = foo2.b;
c = foo2.c;
//.......
}
That's all well but it's quite ugly when this struct has 20+ fields, normally the compiler would hide this from me. Is there a cleaner way to express this, or am I stuck with this big ugly constructor?
You could wrap just your mutex in a copyable class:
struct CopyableMutex {
std::mutex mutex;
CopyableMutex() = default;
CopyableMutex(const CopyableMutex&) {};
CopyableMutex& operator= (const CopyableMutex&) {
return *this;
};
};
struct foo {
CopyableMutex m_foo_mutex;
int a;
int b;
int c;
};
You might want to come up with a better name than CopyableMutex though, as obviously it isn't actually copying the mutex!

Create derived struct from base

I have a POD struct from a library with many data fields:
struct A {
int foo1;
float foo2;
...
};
Now I would like to extend it to add some custom data and thought of this:
struct B : public A {
int bar1;
bool bar2;
};
What is a good way to create an instance of B from an instance of A? This does not work:
A a;
B b = a;
(edit: removed the suggestion to add a constructor B(A const &), OP's update suggests that the given structs should not be modified.)
You can create a B and then use the compiler-generated A::operator=(A&):
A a = { whatever };
B b = { whatever };
static_cast<A &>(b) = a;
If you don't insist on inheritance, beginning with an A would work.
There's no change in memory-layout.
With inheritance, do it in two steps:
Create derived: B b;
Instead with 0-init: B b = {0};
Copy all members: (A&)b = a.
The compiler should be able to optimize that.
Anyway, if possible start with the derived instead of copying.
Make struct B contain a member of type A.
Try this:
b = dynamic_cast<B*>(a);

C++ anonymous class with an initializer

Based on this question (asked a while ago)
inline-object-instantiation-and-transformation-in-java
Is there a way to instantiate and object and initialize it's members in a single line of c++, without the use of a constructor?
In java, as per the link:
JFrame aFrame = new JFrame();
aFrame.add(new JPanel() {{
setSize(100,100);
setLocation(50,50);
setBackground(Color.red);
}});
Can this be done in any way in c++?
EDIT: For example
class Foo{
public:
int test;
int test2;
};
int main(){
Foo foo(){{test=5 test2=4}}; //Like this
}
If the class is an aggregate (with no base classes, non-public members, virtual functions or user-declared constuctors), then you can use aggregate initialisation to initialise its members:
struct thing {
int a,b,c;
};
thing t = {1,2,3};
Otherwise, it can only be initialised by a constructor.
There's one idiom that allows syntax similar to Java. As with everything, it has its downsides as well. I'll leave it up to you to figure out whether it's right for this.
class Foo {
int a;
int b;
int c;
public:
Foo &setA(int val) {a = val; return *this;}
Foo &setB(int val) {b = val; return *this;}
Foo &setC(int val) {c = val; return *this;}
};
Now you can do the following:
auto foo = Foo().setB(2).setA(1).setC(3);
You can apply it to as many or few members as desired. However, it can be tricky in some cases to ensure you always have a valid object. Required initialization can go in the constructor.
Something along these lines that might be more natural is Boost.Parameter, which offers named parameter support that you can use to combine meaningful names with constructor arguments.
That is not an anonymous class. An anonymous class is one without a name.
If you want an anonymous (temporary) instance, and you can initialize it like so:
struct Foo {
int a;
int b;
};
void bar(Foo const &);
int main() {
bar(Foo{1,2});
}
See Mike's answer for the equivalent for a named instance of the named structure. The aggregate constraint is the same.

Is it possible to "add" to the default copy constructor?

Is it possible to "add" to the default copy constructor?
Eg. For this class:
class A
{
public:
int a;
int* b;
};
I want to just write
A::A(const A& rvalue):
a(rvalue.a),
b(new int(*(rvalue.b)))
{}
without the a(rvalue.a) part.
(Ignore the bad/ugly code and possible memory leaks)
What you ask for is impossible. Once you declare your own copy constructor the compiler will not generate a copy constructor for you. That means you won't be able to simply add or augment the default copy constructor because it won't exist. It's all or nothing, so to speak.
it is impossible. However, if you want to reduce redundant code for a large number of "default copied" fields, it may be achieved with intermdiate inheritance:
struct A1 {
int a1;
int a2;
// ....
int aN;
};
struct A:public A1
{
int* b;
A(const A& rhs): A1(rhs), b(new int(*(rhs.b))) {}
};
What you want to do is not nartually supported by C++ : you cannot have half default constructor.
But what you want to achieve can be done by the little trick below:
please note this small demo below have a lot defects(memory leak etc), so it's ONLY for demostration the tentative solution only:
//class A hasa large number date members(but all can take advantage of default
//copy constructor
struct A{
A(int i):a(i){}
int a;
//much more data memberS can use default copy constructor all in class A
};
//class B is simply wrapper for class A
//so class B can use the default constructor of A
//while just write copy constructor for a raw pointer in it's copy constructor
//I think this is what OP want ?
struct B
{
B(int i,int j):m_a(i),m_b(new int(j)){}
B(const B & rval):
m_a(rval.m_a),
m_b(new int(*rval.m_b))
{
}
A m_a;
int * m_b;
};
int main()
{
B c(2,3); // a=2, *m_b=3
B d(c); //after copy constructor, a=2, *m_b=3
}

C++ defining constructor make object non POD

If I have a simple struct Foo, defined like this, it's a POD:
#include <iostream>
#include <type_traits>
struct Foo {
int a;
int b;
bool c;
};
int main() {
std::cout << (std::is_pod<Foo>::value ? "POD" : "NON POD") << '\n'; // Prints "POD"
}
Now imagine I want to default initalize the members and directly do:
struct Foo {
int a;
int b;
bool c = true;
};
The struct is no longer a POD! Even with a constructor like this:
struct Foo {
int a;
int b;
bool c;
Foo() : a(0), b(0), c(false) {}
};
Foo has lost its PODness...
Now the tricky part begins. Imagine I want to add a constructor taking an a:
struct Foo {
int a;
int b;
bool c;
Foo(int a) : a(a), b(0), c(false) {}
};
Now Foo is definitely not a POD. BUT if a add a default constructor:
struct Foo {
int a;
int b;
bool c;
Foo() = default;
Foo(int a) : a(a), b(0), c(false) {}
};
Foo is now a POD!
So as you can see, even if I simply want to use a default value like in the second example, I lose the PODness, but I can regain it as long as I define an explicit default constructor.
So the question is: should we always add a default constructor so we can benefit from the PODness of the class and improve performance? It's too bad to lose performance just because I wanted to default initialize some members...
In other words, defining default value like in the second example makes the struct non POD and non trivial, which is bad performance-wise, so how can I default initialize values and keep the struct trivial? A simple solution would be to define an initFoo function that returns a default initialized Foo, like for example:
Foo initFoo() {
Foo foo;
foo.a = 0;
foo.b = 1;
foo.c = true;
return foo;
}
But this is not very C++, but is it the right thing to do anyway?
should we always add a default constructor so we can benefit from the PODness of the class
If you want a class to be POD, then it must be trivially default constructible, among the other requirements.
One way to achieve that requirement is to not declare any constructors nor default member initialisers. Another way is to define the default constructor as default. Latter is the only way if you want the class to have any non-default constructors.
It doesn't matter which approach you pick as far as PODness is concerned.
but is it the right thing to do anyway?
Your initFoo is a right way to return a Foo with specific values. Personally, I don't see value in the local variable, and would do this instead:
return {
0,
1,
true,
};
Unfortunately, we lose member names from the initialisers, at least until C++20 where we can write:
return {
.a = 0,
.b = 1,
.c = true,
};