Array converted implicitly to container class when passed as argument in C++ - c++

I was working on a project and, while playing around with the code, I came across the following peculiar occurrence.
I have two classes. The first holds three floats in an array representing Cartesian coordinates and defines a method to get those points;
class foo
{
protected:
float m_Coordinates[3];
public:
foo(float coordinates[3]);
void GetPoints(int resultArray[]);
};
foo::foo(int coordinates[3])
{
std::copy(coordinates, coordinates+3, m_Coordinates);
}
void foo::GetPoints(float resultArray[])
{
std::copy(m_Coordinates, m_Coordinates+3, resultArray);
}
The second class also stores an array of floats, but its constructor uses foo as a wrapper class to pass the values:
class bar
{
protected:
float m_MoreCoordinates[3];
public:
bar(foo f);
};
bar::bar(foo f)
{
f.GetPoints(m_MoreCoordinates);
//m_MoreCoordinates is passed by reference, so the values in
//m_MoreCoordinates are equal to the values in f.m_Coordinates
//after this line executes
}
Please ignore the fact that the approach I've taken to this code is simply horrible. It started out as an experiment in using arrays. Passing them as arguments, getting them as return types etc.
OK. Here's where I noticed something strange. If I declare an array of floats and pass them as an argument to bar's constructor, the compiler will generate an instance of class foo and pass that to bar for me. See example code below:
int main(int argv, char** argc)
{
float coordinates[] = {1.0f, 2.1f, 3.0f};
//Here the compiler creates an instance of class foo and passes
//coordinates as the argument to the constructor. It then passes
//the resulting class to bar's constructor.
bar* b = new bar(coordinates);
//Effectively, the compiler turns the previous line into
//bar* b = new bar(foo(coordinates));
return 0;
}
When I saw this, I thought it was a pretty neat feature of the code and was wondering how and why it happened. Is it safe to do this? I don't understand how it works, and so I don't want to depend on it. If someone could explain how this works, I'd really appreciate it.
Edit:
Thanks to Mankarse for pointing out how the conversion would be performed in the main. Initially, I had:
//Effectively, the compiler turns the previous line into
//bar* b = new bar(*(new foo(coordinates)));

As you guessed, compiler is implicitly creating a foo object and passing it to bar. Generally, this is considered a bit dangerous as the foo gets constructed without knowledge, to avoid this you can declare foos constructor as explicit. In that case compiler will not implicitly create foo from array of floats and you will get an compiler error.

When you think about it, you use this all of the time. Consider the following:
void foo(std::string argument);
Then, suppose you invoke this function using a string literal:
foo("argument");
this is the same as:
std::string argument("argument");
foo(argument);
It's a pretty useful feature.

Related

Writing a struct template with two vectors

What I am trying to achieve is create a template of a struct myVector which would contain two vectors i.e. vector_a and vector_b. But i am quite new to templates. I mean, I know why and when one would prefer using Templates in certain situations but I am not quite sure how to tackle this problem. What I have written is:
'''
#include<iostream>
#include<stddef.h>
#include<vector>
template <typename T> struct myVector {
std::vector<T> vector_a;
std::vector<T> vector_b;
};
int main() {
myVector<int> z1(5);
myVector<int> z2(6);
}
'''
I end up getting errors like no matching function for call to ‘VectorXY::VectorXY(int)’
for the vector VectorXY z2(6);
Therefore, I would really appreciate your help. Thanks in advance.
Your error has nothing to do with templates. Consider the following code
struct Int { int i; };
int main()
{
Int z(1); // doesn't compile
}
and you get the error, no matching constructor Int(int).
Classes are an abstraction over something else. It might seem obvious that an int and an Int in this case are the same thing, and constructing one should be like constructing the other. But the compiler doesn't know that, so you need to provide a constructor that passes the argument onto the member.
struct Int
{
int i;
Int(int n) : i(n) {}
};
Note that in C++20, the compiler will actually be able to figure out that you want to use each constructor argument to initialize the corresponding member of your class, so even without a provided constructor, the Int will work like an int.
However, even in that case, your code would not work, since you need to use more complicated rules to construct your members. In your case, you'll need something like
myVector(int n) : vector_a(n), vector_b(n) {}
Assuming that you want the internal vectors to be constructed with the value passed into the constructor. Based on your calling code, it seems that's what you want, but you can write any logic in the constructor.

C++ change pointer to function's parameters to be an array parameter

I have a class with an array who's size is specified in the constructor. The class also stores a pointer to a function that takes a pointer as a parameter which, when called, will be set to point to the array. I also have a "bind" function which sets the function pointer equal to some other function passed in as a parameter. This allows me to bind arbitrary functions who's parameters will contain the array. It looks like this:
template <typename T>
class MyClass{
public:
MyClass(int s) : size(s) { arr = new T[size]; }
MyClass() { delete[] arr; }
virtual inline void bindFunc(void(*func)(T[])) { fn = func; } //types match, ok
inline void callFunc(){fn(arr);}
/*Yes, I know I need a size parameter to correctly
iterate over arr, I took out this info to help make things more clear, just pretend
arr is null terminated and the bound fn function knows how to correctly handle it*/
private:
const int size;
T arr[];
void(*fn)(T[]);
};
This works fine and all, but the point of using arrays (or any container type) was so classes that inherit from MyClass can specify an explicit size. I then planned to (somehow) override the bindFunc function to take a pointer to a function that has an explicit number of separate parameters instead of a pointer to a function with an array of parameters. This is simply to clean up the syntax and make the derived class hide implementation. It would look something like this:
class derived: public MyClass<double> {
public:
derived() : MyClass(2) {}
inline void bindFunc(void(*func)(double, double)) { fn = func; } //error, type mismatch, obviously
};
The error occurs where fn = func because fn is a pointer to a function that takes an array(pointer) as a parameter and func is a pointer to a function that takes 2 doubles as parameters. This is the crux of the problem that I do not know how to fix.
Of course, in this snippet I slimmed down the code a bit to only contain the relevant parts and renamed everything to better portray my problem. If it helps, the original purpose of the class was to store state information passed in from GLFW's callback functions. The derived class(es) were supposed to hold scroll and mouse position info respectively (1 element for scroll position, 2 elements for mouse X/Y position, hence the array who's size is set in the derived class' constructor.) The base class also had functions for calculating other things such as deltas that any other imaginable type of variable input would find useful, hence the hierarchy abstraction. This was all meant to simplify input handling and would've looked something like this when being utilized:
void mouse_callback(GLFWwindow*, double, double);
glfwSetCursorPosCallback(window, mouse_callback);
MyClass *MouseInput = new derived;
void mouseFunction(double x, double y){ //takes 2 doubles instead of array of doubles of size 2
if(x > 0.5)
//do something
if(y < 0.5)
//do something else
}
void main(){
MouseInput->bindFunc(mouseFunction);
MouseInput->callFunc();
}
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
MouseInput->setInfo(xpos, ypos);
/*this function is not shown in the code above, but it basically sets
MouseInput->arr's variables and calls a base class' calculation function
to calculate extra info such as the aforementioned deltas*/
}
I'm not sure if what I want is possible, but I'm interested in learning more about it or a more correct design pattern. I've tried fiddling around with <functional> functions, but I couldn't come up with anything myself. It feels like there would be a feature to the language that would make something like this possible, which is why I cared to type up this question to begin with.
Most of what I experiment with in C++ is for learning and I know my methods might be a little insane for what I'm trying to accomplish, but the hope is it will lead to being a better programmer. Thanks for your insight in advance!
If you use std::function instead of raw function pointers, you can use a lambda to translate the arguments in any way you want:
template <typename T>
class MyClass{
std::function<void(T[])> fn;
public:
virtual inline void bindFunc(void(*func)(T[])) { fn = func; } //types match, ok
virtual inline void bindFunc(void(*func)(T, T)) {
fn = [func](T args[]) { func(args[0], args[1]); }; }
for more flexibility, you can make the func argument a std::function as well

Virtual table pointer and Virtual table simulation

I am trying to simulate the vptr/vtable concept. I have 3 questions regarding the following:
1. I have not defined any constructor for the class FOO , which should be fine as can be seen inside main(Foo *ptr= new FOO is OK ).
But when i create the object on heap for the same inside FooVtable::bar() , it complains about no appropriate default constructor found. Why?
2. I see that vptr points to some address(even though there is no new FooVTable done for vptr,i guess ctor by default does it. is it expected?), FooVtable::bar is getting called but cout doesnt print the statement. Why?
3. Inside callsomeFun(), i am calling foo->vptr->bar . What i am trying to achieve here is that vptr->bar part of foo->vptr->bar should actually call a pointer to member function Foo::bar() , which i guess isnt directly possible, hence i declared void bar(Foo* foo) inside which i am thinking to call the Foo:bar through ptr. Am i approaching it right, or is there a better way to approach this?
class Foo;
struct FooVtable {
void bar(Foo* foo)
{
//Foo *ptr = new Foo; //Why does this throw error as No Default constructor?
cout<"FooVTable : bar"; //Doesnt get printed even though gets called
}
};
struct Foo {
FooVtable* vptr;
void bar(Foo *foo)
{
cout<<"Foo : bar";
}
};
int callSomeFun(Foo* foo) {
foo->vptr->bar(foo);
return 0;
}
int main()
{
Foo *ptr=new Foo;
callSomeFun(ptr);
return 0;
}
when i create the object on heap for the same inside FooVtable::bar() , it complains about no appropriate default constructor found. Why?
That's a poor error message for a situation where you're trying to use a class before it has been fully declared. On a different compiler the message could be more like "error: invalid use of incomplete type 'class Foo'".
One way to solve it would be to put the full struct Foo stuff above FooVtable and then use a forward declaration of FooVtable instead of Foo.
I see that vptr points to some address(even though there is no new FooVTable done for vptr,i guess ctor by default does it. is it expected?), FooVtable::bar is getting called but cout doesnt print the statement. Why?
That vptr is uninitialized. Primitive types like pointers aren't initialized to any kind of default value by just a new. So whatever is in there is garbage. That much is expected.
Whatever happens after you call a function via a pointer with a garbage value is Undefined Behavior. So just about anything could happen and there wouldn't be a guaranteed explanation.
However in this case there's also another problem: You've made a typo. cout<"FooVTable : bar"; has a single < and thus would do a strange and useless comparison instead of outputting anything.
foo->vptr->bar should actually call a pointer to member function Foo::bar() , which i guess isnt directly possible
Pointers to member functions are possible. You could potentially use one in the situation you've created so far. However once you start bringing inheritance into the scenario (which is where virtual functions are finally useful), it could get interesting to try to make this work out between the different types. (I use member function pointers so rarely that I can't say offhand.)
Am i approaching it right, or is there a better way to approach this?
It really depends on how much of a real implementation you're trying to "simulate" and what you're hoping to achieve by it.

c++ variable assignment, is this a normal way..?

This may be a silly question, but still I'm a bit curious...
Recently I was working on one of my former colleague projects, and I've noticed that he really loved to use something like this:
int foo(7);
instead of:
int foo = 7;
Is this a normal/good way to do in C++ language?
Is there some kind of benefits to it? (Or is this just some silly programming style that he was into..?)
This really reminds me a bit of a good way how class member variables can be assigned in the class constructor... something like this:
class MyClass
{
public:
MyClass(int foo) : mFoo(foo)
{ }
private:
int mFoo;
};
instead of this:
class MyClass
{
public:
MyClass(int foo)
{
mFoo = foo;
}
private:
int mFoo;
};
For basic types there's no difference. Use whichever is consistent with the existing code and looks more natural to you.
Otherwise,
A a(x);
performs direct initialization, and
A a = x;
performs copy initialization.
The second part is a member initializer list, there's a bunch of Q&As about it on StackOverflow.
Both are valid. For builtin types they do the same thing; for class types there is a subtle difference.
MyClass m(7); // uses MyClass(int)
MyClass n = 3; // uses MyClass(int) to create a temporary object,
// then uses MyClass(const MyClass&) to copy the
// temporary object into n
The obvious implication is that if MyClass has no copy constructor, or it has one but it isn't accessible, the attempted construction fails. If the construction would succeed, the compiler is allowed to skip the copy constructor and use MyClass(int) directly.
All the answers above are correct. Just add that to it that C++11 supports another way, a generic one as they say to initialize variables.
int a = {2} ;
or
int a {2} ;
Several other good answers point out the difference between constructing "in place" (ClassType v(<constructor args>)) and creating a temporary object and using the copy constructor to copy it (ClassType v = <constructor arg>). Two additional points need to be made, I think. First, the second form obviously has only a single argument, so if your constructor takes more than one argument, you should prefer the first form (yes, there are ways around that, but I think the direct construction is more concise and readable - but, as has been pointed out, that's a personal preferance).
Secondly, the form you use matters if your copy constructor does something significantly different than your standard constructor. This won't be the case most of the time, and some will argue that it's a bad idea to do so, but the language does allow for this to be the case (all surprises you end up dealing with because of it, though, are your own fault).
It's a C++ style of initializing variables - C++ added it for fundamental types so the same form could be used for fundamental and user-defined types. this can be very important for template code that's intended to be instantiated for either kind of type.
Whether you like to use it for normal initialization of fundamental types is a style preference.
Note that C++11 also adds the uniform initialization syntax which allows the same style of initialization to be used for all types - even aggregates like POD structs and arrays (though user defined types may need to have a new type of constructor that takes an initialization list to allow the uniform syntax to be used with them).
Yours is not a silly question at all as things are not as simple as they may seem. Suppose you have:
class A {
public:
A() {}
};
and
class B {
public:
class B(A const &) {}
};
Writing
B b = B(A());
Requires that B's copy constructor be accessible. Writing
B b = A();
Requires also that B's converting constructor B(A const &) be not declared explicit. On the other hand if you write
A a;
B b(a);
all is well, but if you write
B b(A());
This is interpreted by the compiler as the declaration of a function b that takes a nameless argument which is a parameterless function returning A, resulting in mysterious bugs. This is known as C++'s most vexing parse.
I prefer using the parenthetical style...though I always use a space to distinguish from function or method calls, on which I don't use a space:
int foo (7); // initialization
myVector.push_back(7); // method call
One of my reasons for preferring using this across the board for initialization is because it helps remind people that it is not an assignment. Hence overloads to the assignment operator will not apply:
#include <iostream>
class Bar {
private:
int value;
public:
Bar (int value) : value (value) {
std::cout << "code path A" << "\n";
}
Bar& operator=(int right) {
value = right;
std::cout << "code path B" << "\n";
return *this;
}
};
int main() {
Bar b = 7;
b = 7;
return 0;
}
The output is:
code path A
code path B
It feels like the presence of the equals sign obscures the difference. Even if it's "common knowledge" I like to make initialization look notably different than assignment, since we are able to do so.
It's just the syntax for initialization of something :-
SomeClass data(12, 134);
That looks reasonable, but
int data(123);
Looks strange but they are the same syntax.

How do you call a constructor for global objects, for arrays of objects, and for objects inside classes/structs?

How would you call the constructor of the following class in these three situations: Global objects, arrays of objects, and objects contained in another class/struct?
The class with the constructor (used in all three examples):
class Foo {
public:
Foo(int a) { b = a; }
private:
int b;
};
And here are my attempts at calling this constructor:
Global objects
Foo global_foo(3); // works, but I can't control when the constructor is called.
int main() {
// ...
}
Arrays of objects
int main() {
// Array on stack
Foo array_of_foos[30](3); // doesn't work
// Array on heap
Foo *pointer_to_another_array = new Foo(3) [30]; // doesn't work
}
There I'm attempting to call the constructor for all elements of the arrays, but I'd also like to know how to call it on individual elements.
Objects contained in classes/structs
class Bar {
Foo foo(3); // doesn't work
};
int main() {
Bar bar;
}
Global objects
Yours is the only way. On the other hand, try to avoid this. It’s better to use functions (or even other objects) as factories instead. That way, you can control the time of creation.
Arrays of objects
There’s no way to do this directly. Non-POD objects will always be default-constructed. std::fill is often a great help. You might also want to look into allocators and std::uninitialized_fill.
Objects contained in classes/structs
Use initialization lists in your constructor:
class Bar {
Foo foo;
Bar() : foo(3) { }
};
Static members must actually be defined outside the class:
class Bar {
static Foo foo;
};
Foo Bar::foo(3);
To correct some misconceptions about globals:
The order is well defined within a compilation unit.
It is the same as the order of definition
The order across compilation units is undefined.
The order of destruction is the EXACT opposite of creation.
Not something I recommend but: So a simple solution is to to put all globals into a single compilation unit.
Alternatively you can tweak the use of function static variables.
Basically you can have a function the returns a reference to the global you want (defining the global inside the function). It will be created on first use (and destroyed in reverse order of creation).
Foo& getGlobalA() // passed parameters can be passed to constructor
{
static Foo A;
return A;
}
Foo& getGlobalB()
{
static Foo B;
return B;
}
etc.
The Konrad reply is OK, just a puntualization about the arrays....
There is a way to create an array of items(not pointers) and here it follows:
//allocate raw memory for our array
void *rawMemory = operator new[](30 * sizeof(Foo))
// point array_of_foos to this memory so we can use it as an array of Foo
Foo *array_of_foos = static_cast<Foo *>(rawMemory);
// and now we can create the array of objects(NOT pointers to the objects)
// using the buffered new operator
for (int i = 0; i < 30; i++)
new(array_of_foos[i])Foo(3);
This approach is described here: http://www.amazon.com/gp/product/0321334876?ie=UTF8&tag=aristeia.com-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321334876
For the global case there is no way to control when it is called. The C++ spec essentially says it will be called before main() and will be destroyed sometime afterwards. Other than that' the compiler is free to do as it pleases.
In the first array case you are creating a static array of Foo objects. By default each value in the array will be initialized with the default constructor of Foo(). There is no way with a raw C++ array to force a particular overloaded constructor to be called. You can infer a bit of control by switching to a vector instead of an array. The vector constructor has an overloaded constructor vector(size,defaultValue) which should achieve what you are looking for. But in this case you must be careful because instead of calling Foo(3) it will call Foo(const Foo& other) where other is Foo(3).
The second array case is very similar to the first case. The only real difference is where the memory is allocated (on the heap instead of the stack). It has the same limitation with regards to calling to the constructor.
The contained case is a different issue. C++ has a clear separation between the definition of a field within an object and the initialization of the field. To get this to work in C++ you'll need to change your Bar definition to the following
class Bar{
Foo foo;
Bar() : foo(3){}
};
There seems to be the general gist in this thread that you cannot initialize members of an array other than using the default constructor. One answer even creates another type, just to call another constructor. Even though you can (if the array is not part as a member of a class!):
struct foo {
foo(int a): a(a) { }
explicit foo(std::string s): s(s) { }
private:
int a;
std::string s;
};
/* global */
foo f[] = { foo("global"), foo("array") };
int main() {
/* local */
foo f[] = { 10, 20, 30, foo("a"), foo("b") };
}
The type, however, needs to be copy-able: The items given are copy-initialized into the members of the array.
For arrays as members in classes, it's the best to use containers currently:
struct bar {
/* create a vector of 100 foo's, initialized with "initial" */
bar(): f(100, foo("initial")) { }
private:
std::vector<foo> f;
};
Using the placement-new technique described by andy.gurin is an option too. But note it will complicate things. You will have to call destructors yourself. And if any constructor throws, while you are still building up the array, then you need to figure where you stopped... Altogether, if you want to have arrays in your class, and want to initialize them, use of a std::vector is a simple bet.
Construction of arrays of objects:
You can modify your original example by using default parameters.
Currently only the default constructor is supported.
This is something that is being addressed by the next version (because everybody asks this question)
C++0X initializer lists solve this problem for the arrays of objects case. See this Herb Sutter blog entry, where he describes them in detail.
In the meantime you might be able to work around the problem like so:
class Foo {
public:
Foo(int a) : b(a) {}
private:
int b;
};
class Foo_3 : public Foo {
public:
Foo_3() : Foo(3) {}
};
Foo_3 array_of_foos[30];
Here, the Foo_3 class exists solely for the purpose of calling the Foo constructor with the correct argument. You could make it a template even:
template <int i>
class Foo_n : public Foo {
public:
Foo_n() : Foo(i) {}
};
Foo_n<3> array_of_foos[30];
Again this might not do exactly what you want but may provide some food for thought.
(Also note that in your Foo class you really should get into the habit of using member initializer lists instead of assignments in the constructor, as per my example above)
I reckon there are two ways to make sure global class objects' constructors are called safely at the time of their "creation":
Declare them in a namespace and make that namespace globally accessible.
Make it a global pointer to the class object and assign a new class object to it in main(), granted code for other global objects' constructors that access the object will execute before this.
Just my two cents.