Constructor Problems

Write your question here.
1) Why does the program work without the utility header being included for the move function?
2) Why does parenthesis have to be used to initialize firstname and secondname instead of braces?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//	Person.h
//	A class defining a person

#pragma once
#include <iostream>
//#include <utility>
#include <string>

class Person
{
public:
	Person(const std::string first, const std::string second) :
		firstname(std::move(first) ), secondname( std::move(second) ) {}

	Person() = default;

	//	Less_than operator
	bool operator<(const Person& p) const
	{
		return(secondname < p.secondname ||
			((secondname == p.secondname) && (firstname < p.firstname)));
	}

	//	Greater_than operator
	bool operator>(const Person& p) const
	{
		return p < *this;
	}

	//	Output a person
	void showPerson() const
	{
		std::cout << firstname << " " << secondname << std::endl;
	}

private:
	std::string firstname;
	std::string secondname;
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//	Ex10_09.cpp
//	Exercising a priority queue container

#include <vector>
#include <queue>
#include <functional>
#include "Person.h"

int main()
{
	std::priority_queue<Person, std::vector<Person>, std::greater<>> people;
	std::string first, second;
	while (true)
	{
		std::cout << "Enter a first name or press Enter to end: ";
		std::getline(std::cin, first);
		if (first.empty())
			break;


		std::cout << "Enter a second name: ";
		std::getline(std::cin, second);
		people.push(Person{ first, second });
	}

	std::cout << "\nThere are " << people.size() << " people in the queue."
		<< std::endl;

	std::cout << "\nThe names that you entered are : " << std::endl;
	while (!people.empty())
	{
		people.top().showPerson();
		people.pop();
	}

	if (people.empty())
		std::cout << "Priority queue is empty! " << std::endl;

	return 0;
}
1) Why does the program work without the utility header being included for the move function?

You're including iostream and string. One of those files must include utility. Ideally you should not rely on this sort of behavior since it depends on the STL implementation.
2) Why does parenthesis have to be used to initialize firstname and secondname instead of braces?

Are you referring to this?
1
2
	Person(const std::string first, const std::string second) :
		firstname(std::move(first) ), secondname( std::move(second) ) {}
I think the parentheses are used because they specify how to call the constructor of a class. I could be wrong though.
Last edited on
That code doesn't compile, std::greater<> requires a template parameter.
The parenthesis are required in Visual Studio because
error C2797: 'Person::firstname': list initialization inside member initializer list or non-static data member initializer is not implemented

http://msdn.microsoft.com/en-us/library/dn793970.aspx
std::greater used to require a template parameter, until C++14.
I was able to compile the program without specifying a template parameter for std::greater<>.

Before this exercise, I was able to initialize data members using braces. I do not know why in this exercise I am not able to do so.

I will check the iostream and string for the move function.

Thank you all.
Hi,

You could try #include <initializer_list>

It worked for me in some other code I was doing.

Regards

Edit:


http://www.cplusplus.com/reference/initializer_list/initializer_list/
http://en.cppreference.com/w/cpp/utility/initializer_list


Edit2:

I have been using VS2013 Express, and some things are a bit weird: for example I had to include a (or any) header file <iostream> say, so that I could use std::size_t - I haven't had to do that with other IDE / compilers. It's weird because I may not have needed iostream for anything in my header file.
Last edited on
Thanks TheIdeaMan, Cubbi, naraku9333. dhayden,

However, I am not looking for a solution but for an understanding. The program works without the utility header and the braces.

The way I see it is that the colon separates the parameter list from the initializing list, firstname(std::move(first)), secondname(std::move(second)). The complier error message says that list initialization inside member initializer list is not implemented. So, what does this mean? What is the member initializer list?

In another exercise, I was able to use braces.
1
2
CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0) :
     m_Length {lv}, m_Width {wv}, m_Height {hv} {}


I find it mind boggling that I am not able to use braces since braces are used to initialize objects and variables.

As for the move function, iostream does not contain anything. string has a move constructor string (string&& str) noexcept but no move function. How it works without the utility preprocess directive is beyond me.
The complier error message says that list initialization inside member initializer list is not implemented. So, what does this mean?

It means this particular version of the compiler you are using hasn't yet found the time to implement this particular feature of the C++ language, but they were nice enough to say so. The link given by naraku9333 explained it.

What is the member initializer list?

It is the comma-separated list of initializers for bases and members that appears in the constructor after the colon and before the opening curly brace of the constructor's body. It was allowed to use only parenthesized initializers until C++11, at which time brace-init-lists were also allowed. http://en.cppreference.com/w/cpp/language/initializer_list

I find it mind boggling that I am not able to use braces

Then you need a newer version of your compiler (I hear great things about 2015 preview) or a different compiler, for example, here's your program with curly braces compiled by clang: http://coliru.stacked-crooked.com/a/757090d4187ee2cc
Last edited on
Unfortunately it doesn't work in 2015 preview either. Non-static data member initializers are listed as partial support here http://blogs.msdn.com/b/vcblog/archive/2014/11/17/c-11-14-17-features-in-vs-2015-preview.aspx
And explained below
[1] NSDMIs and initializer lists were previously listed as Yes, but have been downgraded to Partial. After users encountered silent bad codegen when using braced-init-lists in NSDMIs and mem-initializer-lists, the compiler team blocked these broken scenarios with a compiler error C2797. This VCBlog post published in August has more info, and this is planned to be completely fixed in 2015 RTM.
Thank you Cubbi and naraku9333. I now understand the error message and the reason why braces are not allowed.

Any idea why the move function works despite the utility preprocessor directive not being included in the program?
The IS allows one standard header to include other standard headers (either in full or in part).

However, portable code should not rely on one standard header being included in another standard header.
(Unless the header synopsis in the IS shows a standard header as including another standard header. For instance, the header <iostream> includes the headers <ios>, <streambuf>, <istream> and <ostream>)

The entities in the C ++ standard library are defined in headers, whose contents are made available to a translation unit when it contains the appropriate #include preprocessing directive.
....
A translation unit shall ... include the header lexically before the first reference in that translation unit to any of the entities declared in that header. - IS
JLBorges,

Thank you so much. Your explanation completes my understanding of this exercise.
Topic archived. No new replies allowed.