Can I use an array as an attribute of struct in C++? - c++

Can I define an array of integers as an attribute in a struct in C++?
This is how I tried, output is also posted:
struct SpaceTime{
SpaceTime(int Coordinates[2][2]):
Coordinates_(Coordinates[2][2]){}
public:
int Coordinates_;
};
int main(){
SpaceTime earth({{100,200},{300,400}});
std::cout << earth.Coordinates_[1][1] << std::endl;
}
Output from C++14, Windows 10 Visual Studio:
.\StackOverFlow.cpp: In function 'int main()':
.\StackOverFlow.cpp:28:39: error: no matching function for call to 'SpaceTime::SpaceTime(<brace-enclosed initializer list>)'
SpaceTime earth({{100,200},{300,400}});
^
.\StackOverFlow.cpp:22:5: note: candidate: SpaceTime::SpaceTime(int (*)[2])
SpaceTime(int Coordinates[2][2]):
^~~~~~~~~
.\StackOverFlow.cpp:22:5: note: no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'int (*)[2]'
.\StackOverFlow.cpp:21:8: note: candidate: constexpr SpaceTime::SpaceTime(const SpaceTime&)
struct SpaceTime{
^~~~~~~~~
.\StackOverFlow.cpp:21:8: note: no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'const SpaceTime&'
.\StackOverFlow.cpp:21:8: note: candidate: constexpr SpaceTime::SpaceTime(SpaceTime&&)
.\StackOverFlow.cpp:21:8: note: no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'SpaceTime&&'
.\StackOverFlow.cpp:29:35: error: invalid types 'int[int]' for array subscript
std::cout << earth.Coordinates_[1][1] << std::endl;

Yes, a C++ data member may be an array. However, your example isn't. Your example Coordinates_ is simply a scalar integer. If you had wanted it to be an array, your class definition should instead appear something like this:
class SpaceTime {
public:
int Coordinates_[2][2];
};
Also, if you want this data member to be initialized by a constructor, that construction would need to perform a deep copy of the data.

Related

In C++, when no constructor is declared for a class, what will happen if I construct an object with arguments?

I have the struct student and I did not declare a constructor. What will happen if I do the following?
struct student{
int assns, mt, finalExam;
float grade(){…}
}
student billy (60, 70, 80);
This answer is written according to the question heading, and not the body, as they seem to be gravely conflicting, hope the OP edits this.
You will encounter a error during compile time.
Code:
#include <iostream>
class test
{
int tt;
};
int main ()
{
test t1 (34);
}
Compiler Error:
In function 'int main()':
10:17: error: no matching function for call to 'test::test(int)' 10:17: note: candidates are:
2:7: note: test::test()
2:7: note: candidate expects 0 arguments, 1 provided
2:7: note: constexpr test::test(const test&)
2:7: note: no known conversion for argument 1 from 'int' to 'const test&'
2:7: note: constexpr test::test(test&&)
2:7: note: no known conversion for argument 1 from 'int' to 'test&&'
This happens as there is no constructor defined which takes a parameter. Without the ctor there is no meaning of class, as you can never initialize its data member, and how can you expect something to be constructed if the construction company itself is absent.
The compiler will throw error.

What does this mean? : note: no known conversion for argument 1 from ‘int’ to ‘const account&’

I'm trying to understand the meaning of the errors that we generally face in out C++ programs.
While compiling a program I got a error (I did this error intentionally, please don't tell that how to correct that) and there a note is present which is :
note: no known conversion for argument 1 from ‘int’ to ‘const account&’
I want to understand the meaning of this note.
My program is :
#include<iostream>
class account
{
private:
int a_no;
public:
account()
{
a_no = 0;
}
void showData()
{
std::cout<<"\n account number = "<<a_no<<std::endl;
}
};
int main()
{
account a1;
a1.showData();
account a2(2);
a2.showData();
return 0;
}
I know that I haven't defined a constructor which can take one argument and doing that will remove my error.
Okay, while compiling this I got:
file1.cpp: In function ‘int main()’:
file1.cpp:20:17: error: no matching function for call to ‘account::account(int)’
account a2(2);
^
file1.cpp:20:17: note: candidates are:
file1.cpp:7:9: note: account::account()
account()
^
file1.cpp:7:9: note: candidate expects 0 arguments, 1 provided
file1.cpp:2:7: note: account::account(const account&)
class account
^
file1.cpp:2:7: note: no known conversion for argument 1 from ‘int’ to ‘const account&’
I want to know what is meaning of last line file1.cpp:2:7: note: no known conversion for argument 1 from ‘int’ to ‘const account&’ ?
1) You already know that you don't have an constructor that takes an int.
2) You know that you are trying to construct account with an int.
3) If you don't do it, compilers will create default copy-constructors, assignment-operators
4) The default copy-constructor takes a const reference to account
So what happens here? As there is only a default-constructor and you are constructing with one parameter the compiler thinks you want to copy-construct. As you are giving him an int as parameter for the copy-constructor, the compiler tries to convert the int to an account - which doesn't work, and he tells you about it: "no conversion possible from int to account"
This is very important to know as this is a source of many bugs. You propably didn't want to call the copy-constructor. But what happens if the compiler really finds a way to convert the type you used as a parameter to account? A mess....
I want to know what is meaning of last line file1.cpp:2:7: note: no known conversion for argument 1 from ‘int’ to ‘const account&’ ?
First, the message tell you
no matching function for call to ‘account::account(int)’
And there're two candidates, the 1st is the default ctor, but
file1.cpp:7:9: note: candidate expects 0 arguments, 1 provided
The 2nd is the copy ctor (implicitly generated), and its parameter's type is const account&, but
file1.cpp:2:7: note: no known conversion for argument 1 from ‘int’ to ‘const account&’
class constructor is a simple function as like as others, so when you send a int type to the function as parameter, you need to define parameter type for function :
class account
{
private:
int a_no;
public:
account(int a){ a_no = a; }
};
now, when you type account a2(2); int type defined for constructor and there isn't any problem

C++11 POD structure initializing error

I have confusing situation with simple code:
struct Item {
size_t span{};
};
int main() {
Item item{1}; // error is here
return 0;
}
While compiling this I have following error:
test.cpp: In function ‘int main()’:
test.cpp:8:13: error: no matching function for call to ‘Item::Item(<brace-enclosed initializer list>)’
Item i{1};
^
test.cpp:8:13: note: candidates are:
test.cpp:3:8: note: constexpr Item::Item()
struct Item {
^
test.cpp:3:8: note: candidate expects 0 arguments, 1 provided
test.cpp:3:8: note: constexpr Item::Item(const Item&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘const Item&’
test.cpp:3:8: note: constexpr Item::Item(Item&&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘int’ to ‘Item&&’
Why g++ tries to find a ctor for initializer list in this case instead of simple C-style structure object creating?
If I remove {} from size_t span{} it compiles successfully.
It also happens if I change the line to size_t span = 0 so it seems to be some initialization in declaration issue which exists since c++11.
Usign Item item{1}; means you're doing list-initialisation (of item). List initialisation is defined as follows:
if the type is an aggregate, aggregate initialisation (what you refer to as "C-style struct object creating") happens
...
if the type is a class, constructors are considered
Your class has no constructors. It is also not a (C++11) aggregate, because it contains an initialiser for a non-static data member.
Note that this restriction (member initialisers) was lifted in C++14, so Item is a C++14 aggregate and your code, while not valid C++11, is valid C++14.

Adding to a Protocol Buffers repeated field

I'm working in C++ with a Protocol Buffer template including the following message:
message StringTable {
repeated bytes s = 1;
}
I'm attempting to add a new value to the existing data, like so:
pb.stringtable().s().Add(replace_key);
However, this generates an error on compilation (using clang on OS X):
test.cpp:51:4: error: member function 'Add' not viable: 'this' argument
has type 'const ::google::protobuf::RepeatedPtrField< ::std::string>',
but function is not marked const
pb.stringtable().s().Add(replace_key);
^~~~~~~~~~~~~~~~~~~~
Any clues? I'm very much a C++ newbie so may be making a dumb error.
Edit:
Using the accessors produces a similar error:
pb.stringtable().add_s(replace_key);
results in:
test.cpp:51:21: error: no matching member function for call to 'add_s'
pb.stringtable().add_s(replace_key);
~~~~~~~~~~~~~~~~~^~~~~
./osmformat.pb.h:3046:26: note: candidate function not viable: 'this' argument has type 'const ::StringTable', but method is not marked const
inline void StringTable::add_s(const ::std::string& value) {
^
./osmformat.pb.h:3050:26: note: candidate function not viable: 'this' argument has type 'const ::StringTable', but method is not marked const
inline void StringTable::add_s(const char* value) {
^
./osmformat.pb.h:3043:36: note: candidate function not viable: requires 0 arguments, but 1 was provided
inline ::std::string* StringTable::add_s() {
^
./osmformat.pb.h:3054:26: note: candidate function not viable: requires 2 arguments, but 1 was provided
inline void StringTable::add_s(const void* value, size_t size) {
Problem solved.
The existing StringTable isn't mutable by default. However, using the mutable_ accessors makes it so:
pb.mutable_stringtable().add_s(replace_key);

Brace-enclosed initializer list of templated struct

#include <array>
#include <vector>
#include <cinttypes>
#include <iostream>
using namespace std;
template<size_t N>
struct item_t {
array<uint32_t, N> weight = {0};
};
int main(void) {
vector<item_t<3>> items;
items.emplace_back({{9,2,3}});
cout << items[0].weight[0] << endl;
return 0;
};
I'm at a bit of a loss here. Error is on the emplace_back line and no idea how to resolve it. Any help or hints would be appreciated, thanks.
EDIT
gcc version 4.8.2
$ g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:16:30: error: no matching function for call to ‘std::vector<item_t<3ul> >::emplace_back(<brace-enclosed initializer list>)’
items.emplace_back({{9,2,3}});
^
test.cpp:16:30: note: candidate is:
In file included from /usr/include/c++/4.8/vector:69:0,
from test.cpp:2:
/usr/include/c++/4.8/bits/vector.tcc:91:7: note: void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = item_t<3ul>; _Alloc = std::allocator<item_t<3ul> >]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:91:7: note: candidate expects 0 arguments, 1 provided
The problem is with the struct initialization = {0} and with emplace_back.
emplace_back() uses template argument deduction to determine the types of the elements passed to the function. A brace enclosed initializer list is not an expression and doesn't have type and therefore cannot be deduced by the template. You have to explicitly call the constructor here:
items.emplace_back(item_t<3>{{1,2,3}});
There are two issues here :
Trying to init a object of type T like this T{...} is referred to as aggregate initialization. Under some conditions, there is a default behaviour specified for it, even if you don't have a constructor which accepts a initializer_list. In C++11, you are not allowed to provide non-default constructors or in-class initializers. So, given this definition
template<size_t N>
struct item_t {
array<uint32_t, N> weight = {0};
};
you cannot write item_t<3> t{1,2,3};.
That, however, isn't your problem. The reason your code fails is that emplace_back tries to forward the arguments to a constructor of the vectors underlying type. In your case, there isn't a match. Note that nice a braced-init list isn't equivalent to an initializer_list in this context, you cannot solve this problem by adding an initializer_list constructor and will have to help the compiler out some other way.