I am new to C++ programming, I am wondering what is "instantiated from here" error?
struct Data {
Data(int a, int b) {
x = a;
y = b;
}
int x;
int y;
};
std::map<int, Data> m;
m[1] = Data(1, 2);
I got several error messages
no matching function for call to "Data::Data()"
"instantiated from here" error
Thanks.
There is no default constructor for struct Data. The map::operator[] returns a default constructed instance of its value type, in this case struct Data.
Either supply a default constructor:
Data() : x(0), y(0) {}
or use std::map::insert():
m.insert(std::pair<int, Data>(1, Data(1, 2)));
C++ what is “instantiated from here” error?
That is not an error, but the continuation of the previous error adding extra information. The compiler is adding the error: prefix so that it is easier to read (or parse) what lines belong to the error.
You can read the whole block as a single error:
No matching function call to Data::Data() instantiated from...
You need to provide a constructor which takes no arguments.
Data::Data(){}
It means that the error (the "No matching function call" one) became obvious only when the compiler started resolving (instantiating) the template std::map::map().
When you insert an item into a map using operator[], what happens is that the map inserts a default-constructed object for the specified key to refer to, then the value you're assigning gets copied into that default constructed object.
To create that default-constructed object, a default constructor needs to be available. In your case, sine you've specified a constructor that takes two arguments (and not supplied default values for those arguments), the compiler will not automatically synthesize a default constructor for you.
Under the circumstances, I'd probably modify your constructor to something like this:
Data(int a=0, int b=0) : x(a), y(b) {}
Note that you should generally prefer initializing variables in an initialization list (if possible) over assigning to them in the body of the constructor.
no matching function for call to "Data::Data()"
You need to provide a default constructor. See the answer to this question:
Template Error: no appropriate default constructor available
"instantiated from here" error
You can only have variable declarations in the global area. You need do that assignment from within a function. Correct code:
#include <map>
struct Data {
Data(int a, int b) {
x = a;
y = b;
}
int x;
int y;
Data() {};
};
std::map<int, Data> m;
void main()
{
m[1] = Data(1, 2);
}
Related
I know it's a subject that has been discussed quite extensively here on stackoverflow but I've a hard time finding thorough answers removing all the confusion I've concerning list initialization and initializer_lists in C++, so I will just give it a try and ask my own questions.
Please, consider the following snippet of code :
class C
{
public :
C(int a, int b, int c) : _a (a), _b(b), _c(c) {}; //initialization_list with ()
//C(int a, int b, int c) : _a{ a }, _b{ b }, _c{ c } {}; //initialization list with {}
private :
int _a, _b, _c;
};
int main()
{
C a(5.3,3.3,4.3); // no list
C b{5.3,3.3,4.3}; // list {}
C c({5.3,3.3,4.3}); // list {}
}
I don't understand why those two initialization lists behave similarly? I was expecting, when trying to create the object a of type C using the initialization list of type _a{a}, _b{b}, _c{c} to get a compiler error about narrowing. However, no errors are generated and _a, _b and _c just store the integer values.
It's only when creating the objects b or c using a list "{}" that the compiler generates a narrowing error message. Why is that? Is there any differences between writing an initialization list using {} or () that I'm unaware of or are the behaviours identical?
Come my next question:
class C
{
public :
//private :
int _a, _b, _c;
};
int main()
{
C a(5,3,4); //obviously doesn't work as no such constructor
C b{5,3,4}; //work only if _a, _b and _c are not private nor protected!
}
How comes that the second statement (with braces) only works if the variables are public? What is the mechanism involved?
So I would like to better understand, beside the "narrowing safety" provided by creating an object with a list {}, what other "functionalities" does this list mechanism provide ? Because in the second call, it's still the default constructor that is called (hence, not a default constructor taking an initializer_list as argument), right ?
Lastly, imagine in my class C I've another constructor taking an initializer list as parameter.
class C
{
public :
C() = default; //default constructor
C(int a, int b, int c) : _a (a), _b(b), _c(c) {};
C(std::initializer_list<int> a) { //do some stuffs with the list};
private :
int _a, _b, _c;
};
It's pretty obvious that, if trying to create an object taking any numbers of integers but 3 (or 0 actually), the constructor taking the initializer_list will be invoked. If creating an object like that however :
C c();
or
C c{};
the default constructor will be called. But if creating an object with exactly 3 integers :
C c(5,2,3);
or
C c{5,2,3};
the initializer_list constructor will be called. The rule goes like that :
If either a default constructor or an initializer-list constructor could be invoked, prefer the default constructor
If both an initializer-list contructor and an "ordinary constructor" could be invoked, prefer the initializer-list constructor
Therefore (and correct me if I'm wrong), if I create my object like that :
C c{5,3,4};
The iniatializer-list constructor will be called. However, if I create my object like that :
C c(5,3,4);
The second constructor (taking 3 ints as arguments) will be called. My question is : how can I create an object with this second constructor instead of the iniatializer-list one if I want to provide narrowing safety as well ? (because if I do as in the first example of this question, the initializer-list constructor will be called instead !).
Don't hesitate to examplify your replies and to discuss on list-related concepts I haven't talk in this question. I would like to get a very good grasp on those. Thanks.
So anytime curly braces are used you are using aggregate initialization, a method of initialization for structs or classes that initializes in order., or via a designator. For example,
#include <iostream>
struct Foo
{
int a;
char b;
};
class Doo
{
public:
double h;
char ch;
};
int main() {
Foo first = {3, 't'};
std::cout << first.b << "\n";
//t
Doo second = {'3', 50};
std::cout << second.ch << "\n";
//2 interpreted as char
}
Here, when we use the {} to initialize a class or struct, they are always interpreted as being in the order listed in the class. That's why '2' was printed since 50 in ASCII corresponds to the character '2'.
Constructor Initialization
So you can also use the same logic with constructor initialization lists,
#include <iostream>
struct Pair
{
int first;
long second;
};
class Couple
{
public:
Pair p;
int g;
public:
Couple(): p{3, 700}, g{3}
{}
};
int main() {
Couple test;
std::cout << test.p.first << "\n";
//3
}
Here, the {3, 700} next to p, would be the same as Pair p = {3, 700}; used else where in code. Your basically using an in order aggregate initialization. Now, what happens if we change the curly braces for the Pair field to parenthesis?
We get this error
main.cpp: In constructor 'Couple::Couple()':
main.cpp:15:26: error: no matching function for call to 'Pair::Pair(int, int)'
Couple(): p(3, 700), g{3}
That's because we don't have a constructor for Pair that accepts two numbers. So the key difference between the aggregate initialization and the parenthesis is you need to have constructors implemented for any specific set of arguments you make with parenthesis, yet with curly braces you can just use the default one the compiler hands you.
The std::initializer_list is a not-commonly used form of container for multiple arguments in initialization lists with {}.
I have the class
class A
{
public:
class Key
{
Key() {}
Key(Key const &) {}
};
A(Key key, int a = 5) {}
};
The constructor for Key is private, so no one should be able to construct an object A. However, with the following code:
int main() {
A a(A::Key()); // this compiles !!!
A a2(A::Key(), 5); // this doesn't
// somehow defaulting the argument causes the private constructor
// to be OK - no idea why
return 0;
}
By making use of the default argument for int a in my constructor, the compiler happily compiles my usage of A::Key() despite the fact that it is private. If I explicitly give a value for a, though, the compiler correctly recognizes that I am trying to use a private constructor and errors out. Why is this? Is there someway to force the compiler to error out for the first example as well?
See here for live example.
This is because of the most vexing parse.
A a(A::Key());
Does not create a A named a and construct it with a temporary A::Key. It creates a function a that returns an A and takes an unnamed pointer to function that returns a A::Key.
If you add a pair of parentheses to it you will get a compiler error
A a((A::Key()));
That you are trying to call a private constructor. Alternatively you can use uniformed initialization which also disambiguate it and will cause a compile error
A a(A::Key{});
I would have initially expected the following code to compile:
#include <set>
using namespace std;
class A {
public:
set<int> st;
A(set<int> s) : st(s) {}
};
int main() {
A a = {1,2,3}; // Error, couldn't convert from initializer list
A b({1,2,3}); // Ok
}
I can't understand why the first construction fails but the second one succeeds. I tried to replicate the error without the use of initializer list but I couldn't do so.
I am using vc12, but it also fails on the microsoft online visual compiler (with a different error message and code to my compiler).
Should this compile?
If not why not?
EDIT:
The following does compile (EDIT: Only in visual studio and this is a bug.):
class A {
public:
int i;
A(int j) : i(i) {}
};
class B {
public:
A a;
B(A o) : a(o) {}
};
class C {
public:
B b;
C(B u) : b(u) {}
};
int main() {
C c = A(10); // Compiles just fine, but isn't this doing the same set of implicit conversions?
C v(A(10));
}
The two seem the same to me in terms of the number of implicit conversions.
Given this code:
#include <set>
using namespace std;
class A {
public:
set<int> st;
A(set<int> s) : st(s) {}
};
int main() {
A a = {1,2,3}; // Error, couldn't convert from initializer list
A b({1,2,3}); // Ok
}
The declaration of a, using the “=” syntax, is a copy initialization with a brace-enclosed list.
If A were a Plain Old Data type or an “aggregate” then the values in the list would be used to initialize the items of a in order, and the rest of the items, if any, would be zero-initialized.
If A instead had a constructor taking a suitable std::initializer_list argument, then that would have been used.
Those two possibilities are exhaustive. For example, if the constructor with std::set had been considered (it isn't considered), then that would have involved two implicit user-defined conversions to produce the temporary object on the right hand side of =, namely std:initializer_list → std::set, and then std:.set → A. And the rules of C++ limit an implicit conversion sequence to at most one user defined conversion.
And so, since class A is neither POD/aggregate nor a class with std::initializer_list construction, you get an error.
The declaration of b is direct initialization. Here the provided argument is used not to produce a temporary A, but to produce an argument acceptable to some A constructor. One such possibility is found: using the argument to produce a std::set.
When initializing an object with = the compiler implicitly creates a temporary object of your type and then copies it to your variable (although the temporary and copy may, and usually are, elided).
So your a object is theoretically equivalent to:
A a = A(std::set<int>({1, 2, 3}));
I'm not sure exactly why the behaviour differs but I think it's due to the fact that the compiler is allowed to only perform one user defined conversion implicitly. In this case it's probably considered two separate UDCs:
initializer list to std::set
std::set to A
In first case you are trying to construct your object using constructor which takes an std::initializer_list as single parameter (which is not implemented). In your second call a temporary std::set<int> instance is constructed and your A(set<int> s) constructor is called.
In order to fix it implement the missing constructor:
A(std::initializer_list<int> list) : st(list) { }
Gotw 80 includes the following example:
// Example 1
//
#include <string>
using namespace std;
class A
{
public:
A( const string& s ) { /* ... */ }
string f() { return "hello, world"; }
};
class B : public A
{
public:
B() : A( s = f() ) {}
private:
string s;
};
int main()
{
B b;
}
The article goes to discuss why the line s = f() is incorrect - due to object lifetimes and order of construction. The article states that at the time, the error wasn't picked up by the compiler.
However, ignoring the problems of order of intialisation and object lifetime, I don't see how s = f() in the parameter list of the constructor can be legal syntactically - it appears to be trying to initialise a member in the parameter list (or perhaps declaring a default value). Can anyone explain what this syntax is trying to do?
It looks like the intention was to call f() and assign the result to B::s. Afterward, the result of that assignment (which is s) would be used as actual parameter when calling the inherited A constructor.
It's syntactically valid. Replace s in that expression with some non-member variable, and g++ accepts it without issue. You might see similar syntax used more often with ordinary function calls instead of constructor calls.
Syntactically it's legal... when you have a base class with a constructor that takes arguments you can of course pass any expression as parameter:
strut A {
A(int) {}
};
struct B : A {
B() : A( any expression that returns an int ) {}
};
The problem is that when evaluating the expression in the example the object is not even yet a fully constructed A instance, so that code is invalid for two distinct reasons:
Calls a method of A of an non-instance (the constructor didn't start yet): f() call is illegal.
Assigns to a member that hasn't been initialized: s=... is illegal.
I'm reading this C++ open source code and I came to a constructor but I don't get it ( basically because I don't know C++ :P )
I understand C and Java very well.
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
As far I can "deduce" The first line only declares the construtor name, the "::" sounds like "belongs to" to me. And the code between {} is the constructor body it self.
I "think" what's after the paremeters and the first "{" are like methods default parameters or something, but I don't find a reasonable explanation on the web. Most of the C++ constructors that I found in the examples are almost identical to those in Java.
I'm I right in my assumptions? "::" is like belongs to, and the list after params and body are like "default args" or something?
UPDATE:
Thanks for the answers.
May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
The most common case is this:
class foo{
private:
int x;
int y;
public:
foo(int _x, int _y) : x(_x), y(_y) {}
}
This will set x and y to the values that are given in _x and _y in the constructor parameters. This is often the best way to construct any objects that are declared as data members.
It is also possible that you were looking at constructor chaining:
class foo : public bar{
foo(int x, int y) : bar(x, y) {}
};
In this instance, the class's constructor will call the constructor of its base class and pass the values x and y.
To dissect the function even further:
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
The ::-operator is called the scope resolution operator. It basically just indicates that TransparentObject is a member of TransparentObject. Secondly, you are correct in assuming that the body of the constructor occurs in the curly braces.
UPDATE: Thanks for the answers. May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
There is much more information on this subject than I could possibly ever give you here. The most common area where you have to use initializer lists is when you're initializing a reference or a const as these variables must be given a value immediately upon creation.
You are pretty close. The first line is the declaration. The label left of the :: is the class name and for it to be a constructor, the function name has to be the same as the class name.
TransparentObject::TransparentObject( int w, int x, int y, int z )
In C++ you can optionally put a colon and some initial values for member variables before the start of the function body. This technique must be used if you are initialzing any const variables or passing parameters to a superclass constructor.
:
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
And then comes the body of the constructor in curly braces.
{
int bla;
int bla;
}
:: Actually means contains (see comments for clarification), however the _someMethods and so forth is what's called an initialisation list. There is plenty of info at the link =]
EDIT: Sorry, my first sentence is incorrect - see the comments.
Yes, :: is the C++ scoping operator which lets you tell the compiler what the function belongs to. Using a : after the constructor declaration starts what is called an initialization list.
The code between the argument list and the {}s specifies the initialization of (some of) the class members.
Initialization as opposed to assignment---they are different things---so these are all calls to constructors.
You're correct. Its a way to set the default values for the class variables. I'm not too familiar with the exact difference between putting them after : and in the function body.
There are usually some good reasons to use an initialization list. For one, you cannot set member variables that are references outside of the initialization list of the constructor. Also if a member variable needs certain arguments to its own constructor, you have to pass them in here. Compare this:
class A
{
public:
A();
private:
B _b;
C& _c;
};
A::A( C& someC )
{
_c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
_b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very
// expensive construction that shouldn't be done more than once
}
to this version:
A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}
Without using the initialiser list all class members will simply have their default constructor called so this is the only place that you can control which constructor is called (for non-dynamically allocated members). The same is true for which parent class constructor will be called.
Class members "initialised" within the body of the constructor (i.e. between the {} braces using the = operator) isn't technically initialisation, it's an assignment. For classes with a non-trivial constructor/destructor it can be costly to default construct and then modify through assignment in this way. For reference members you must use the initialiser list since they cannot be changed via the assignment operator.
If the member (or parent class) does not have a default constructor then failing to specify an appropriate constructor in the initialiser list will cause the compiler to generate an error. Otherwise the compiler will insert the default constructor calls itself. For built in types this does nothing so you will have garbage values there.
Note that the order in which you specify the members in the initialiser list does not affect the order in which they are called. It is always the parent class constructor (if any) first, then the class members in the order in which they are defined in the class definition. The order in which you put them in the initialiser list does not matter and can be the source of subtle bugs...
In the contrived example below it looks like the intention is to initialise m_b with value then m_a with m_b, but what actually happens is that m_a is initialised with m_b (which is itself not yet initialised) then m_b gets initialised with value. m_b will just contain garbage!
struct BadInitialiserListExample
{
BadInitialiserListExample(int value) :
m_b(value),
m_a(m_b) // <-- *BUG* this is actually executed first due to ordering below!
{
}
int m_a;
int m_b;
};