Channels ▼
RSS

Web Development

New C++ Language Features in Visual Studio 2013


The following lines show the code for a brace_demo class that has three member variables (m_name, m_age, and m_score) and four constructors, including a default. The default constructor doesn't initialize any member variable. The other constructors initialize one (m_name), two (m_name and m_age), and all the member variables (m_name, m_age, and m_score).

class brace_demo {
public:
	brace_demo() {}
	brace_demo(string name) : m_name{ name } {}
	brace_demo(string name, int age) : m_name{ name }, m_age{ age } {}
	brace_demo(string name, int age, double score) : m_name{ name }, m_age{ age }, m_score{ score } {}
	string m_name;
	int m_age;
	double m_score;
};

The following lines use many brace initializations that call different constructors for the brace_demo class. Just to increase the fun, I've used raw string literals to demonstrate more C++11 features in the code.

brace_demo demo_default{};
brace_demo demo_default_2;

brace_demo demo_with_name{ R"(Name with "double quotes")" };
brace_demo demo_with_name_and_age{ R"(Name with "age")", 30 };
brace_demo demo_with_name_age_and_score{ R"(Name with "age" and "score")", 30, 3.5 };

The long variable names allow you to easily understand which constructor is being called in each case. demo_default and demo_default_2 call the default constructor, which doesn't initialize any member variable. In the first case, the code uses empty braces; and in the second case, there are no braces. Both lines produce the same result — the call to the default constructor.

demo_with_name calls the constructor that only initializes m_name. The following line would produce the same result:

brace_demo demo_with_name(R"(Name with "double quotes")");

demo_with_name_and_age and demo_with_name_age_and_score call the other constructors, which initialize the variables clearly indicated in the names. The following lines would produce the same result:

brace_demo demo_with_name_and_age(R"(Name with "age")", 30);
brace_demo demo_with_name_age_and_score(R"(Name with "age" and "score")", 30, 3.5);

If the type doesn't have a declared constructor, the brace initializer must specify the values for the members using the same order in which these members are declared. For example, the following lines show a different version of the brace_demo class that doesn't have declared constructors:

class brace_demo {
public:
	string m_name;
	int m_age;
	double m_score;
};

The following lines use brace initializations and will also work with the new brace_demo class because the brace initializers specify the values for the members using the same order in which these members were declared in the class:

brace_demo demo_default{};
brace_demo demo_default_2;

brace_demo demo_with_name{ R"(Name with "double quotes")" };
brace_demo demo_with_name_and_age{ R"(Name with "age")", 30 };
brace_demo demo_with_name_age_and_score{ R"(Name with "age" and "score")", 30, 3.5 };

However, the next lines will produce compiler errors because there are no constructors that match the argument list. Brace initialization works, but the classic calls to inexistent constructors don't.

brace_demo demo_with_name(R"(Name with "double quotes")");
brace_demo demo_with_name_and_age(R"(Name with "age")", 30);
brace_demo demo_with_name_age_and_score(R"(Name with "age" and "score")", 30, 3.5);

It is also possible to use brace initialization in other situations where you perform an initialization. For example, you can use brace initialization with the new keyword, as shown in the following line:

brace_demo* demo_with_new = new brace_demo{ R"(Name with "age" and "score")", 30, 3.5 };

In addition, don't be surprised if you see brace initialization being used in a return statement or with function parameters. For example, the following line is valid:

return { 0 };

Visual Studio 2013 has also added support for initializer lists. You can use brace initialization to construct a std::initializer_list<T> that represents a list of objects of a specified type; therefore, any method or constructor that takes a std::initializer_list<T> as an argument can benefit from brace initialization. Now, all the standard library container classes have std::initializer_list<T> constructors. In addition, string, wstring, and regex include std::initializer_list<T> constructors.

The following lines show the construction of a std::initializer_list<double> with brace initialization. The code includes the required include and using statements that you will employ whenever you want to work with std::initializer_list<T>.

#include <initializer_list>
using namespace std;
initializer_list<double> double_list{ 2.5, 3.0, 5.5, 3.42 };

The following line shows an example of using brace initialization to construct a string:

string header { 'B', 'R', 'A', 'C', 'E', ' ', 'I', 'N', 'I', 'T', 'I', 'A', 'L', 'I', 'Z', 'A', 'T', 'I', 'O', 'N' };

The following lines show the construction of a std::map<string, int> with brace initialization.

#include <initializer_list>
#include <map>
using namespace std;

map<string, int> positions
{ 
	{ "FIRST", 1 }, 
	{ "SECOND", 2 }, 
	{ "THIRD", 3 }, 
	{ "FOURTH", 4 } 
};

You can easily use initializer lists in your own functions. For example, the following lines show a simple size function that has a std::initializer_list<string> as an argument and returns the sum of the sizes of the received strings.

#include <string>
#include <initializer_list>
#include <map>
using namespace std;

int size(const initializer_list<string>& strings)
{
	int result = 0;
	for (auto str : strings)
	{
		result += str.size();
	}

	return { result };
}

The following line calls the size function with a std::initializer_list<string> that contains four strings:

auto total_size = size({ "ONE", "TWO", "THREE", "FOUR" });

Reducing Duplicate Code with Delegating Constructors

When a class has multiple constructors, they often do similar things and require the same pieces of code to be executed. This situation leads to the presence of duplicate code in the different constructors. Visual Studio 2013 has support for delegating constructors. You can use this feature to make one constructor delegate some of the work to another constructor. Delegating constructors allows you to reduce repetitive code (though you are still responsible for preventing the accidental creation of constructor recursion). If you've worked with C#, you probably miss this feature when you code in C++.

The following lines show the code for a simple screen_point class, which provides four constructors that all call the common initialize method to avoid code duplication. A screen_point is considered to be incomplete whenever it lacks one of the three parameters: x, y, or alpha. It is possible to generate a better version of the code with the use of delegating constructors.

class screen_point {
public:
	screen_point() {
		initialize(true, -1, -1, -1);
	}

	screen_point(double x) {
		initialize(true, x, -1, -1);
	}
	
	screen_point(double x, double y) {
		initialize(true, x, y, -1);
	}

	screen_point(double x, double y, double alpha) {
		initialize(false, x, y, alpha);
	}

	double m_x;
	double m_y;
	double m_alpha;
	bool m_incomplete_point;
private:
	void initialize(bool incomplete_point, double x, double y, double alpha) {
		m_incomplete_point = incomplete_point;
		m_x = x;
		m_y = y;
		m_alpha = alpha;
	}
}; 

The following three lines that use brace initialization will generate screen_point instances with m_incomplete_point equal to true:

screen_point incomplete_point1{};
screen_point incomplete_point2{ 5.5 };
screen_point incomplete_point3{ 5.5, 3.0 };

The following line also uses brace initialization and will generate a complete screen_point:

screen_point point{ 5.5, 3.0, 0.9 };

The following lines show a new version of the screen_point class using the delegating constructors feature. Notice that each constructor delegates work to the previously defined constructor. This way, all the necessary initialization code is included in each constructor and there is no duplicate code. There is no need to create a common initialize method because each constructor does its necessary initialization work.

class screen_point {
public:
	screen_point() {}

	screen_point(double x) : screen_point() {
		m_x = x;
	}

	screen_point(double x, double y) : screen_point(x) {
		m_y = y;
	}

	screen_point(double x, double y, double alpha) : screen_point(x, y) {
		m_alpha = alpha;
		m_incomplete_point = false;
	}

	double m_x{ -1 };
	double m_y{ -1 };
	double m_alpha{ -1 };
	bool m_incomplete_point{ true };
};

As you can see from this example, the use of delegating constructors simplifies code when you have multiple constructors and definitely makes the code easier to read and maintain (because you can easily see how the different constructors are chained).

Conclusion

Raw string literals, brace initialization, initializer list constructors, and delegating constructors are just a few of the goodies supported in Visual Studio 2013. In the next article, I'll provide examples of other useful ISO C++11 core language specifications and ISO C++14 library features supported in Visual Studio 2013.


Gaston Hillar is a frequent contributor to Dr. Dobb's.

Related Reading

More New Features in VS2013


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV