Skip to content

Commit 00f50ff

Browse files
authored
Merge pull request MicrosoftDocs#2593 from MicrosoftDocs/master
12/30/2019 AM Publish
2 parents ef34a11 + 8eebb52 commit 00f50ff

File tree

4 files changed

+68
-16
lines changed

4 files changed

+68
-16
lines changed

docs/cpp/constructors-cpp.md

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Constructors (C++)"
3-
ms.date: "11/19/2019"
3+
ms.date: "12/27/2019"
44
helpviewer_keywords: ["constructors [C++]", "objects [C++], creating", "instance constructors"]
55
ms.assetid: 3e9f7211-313a-4a92-9584-337452e061a9
66
---
@@ -469,6 +469,52 @@ If a constructor throws an exception, the order of destruction is the reverse of
469469
470470
1. If the constructor is non-delegating, all fully-constructed base class objects and members are destroyed. However, because the object itself is not fully constructed, the destructor is not run.
471471
472+
## <a name="extended_aggregate"></a> Derived constructors and extended aggregate initialization
473+
474+
If the constructor of a base class is non-public, but accessible to a derived class, then under **/std:c++17** mode in Visual Studio 2017 and later you can't use empty braces to initialize an object of the derived type.
475+
476+
The following example shows C++14 conformant behavior:
477+
478+
```cpp
479+
struct Derived;
480+
481+
struct Base {
482+
friend struct Derived;
483+
private:
484+
Base() {}
485+
};
486+
487+
struct Derived : Base {};
488+
489+
Derived d1; // OK. No aggregate init involved.
490+
Derived d2 {}; // OK in C++14: Calls Derived::Derived()
491+
// which can call Base ctor.
492+
```
493+
494+
In C++17, `Derived` is now considered an aggregate type. It means that the initialization of `Base` via the private default constructor happens directly, as part of the extended aggregate initialization rule. Previously, the `Base` private constructor was called via the `Derived` constructor, and it succeeded because of the friend declaration.
495+
496+
The following example shows C++17 behavior in Visual Studio 2017 and later in **/std:c++17** mode:
497+
498+
```cpp
499+
struct Derived;
500+
501+
struct Base {
502+
friend struct Derived;
503+
private:
504+
Base() {}
505+
};
506+
507+
struct Derived : Base {
508+
Derived() {} // add user-defined constructor
509+
// to call with {} initialization
510+
};
511+
512+
Derived d1; // OK. No aggregate init involved.
513+
514+
Derived d2 {}; // error C2248: 'Base::Base': cannot access
515+
// private member declared in class 'Base'
516+
```
517+
472518
### Constructors for classes that have multiple inheritance
473519
474520
If a class is derived from multiple base classes, the base class constructors are invoked in the order in which they are listed in the declaration of the derived class:

docs/cpp/initializing-classes-and-structs-without-constructors-cpp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ kr->add_d({ 4.5 });
131131
return { 4.5 };
132132
```
133133
134+
In **/std:c++17** mode, the rules for empty brace initialization are slightly more restrictive. See [Derived constructors and extended aggregate initialization](constructors-cpp.md#extended_aggregate).
135+
134136
## initializer_list constructors
135137
136138
The [initializer_list Class](../standard-library/initializer-list-class.md) represents a list of objects of a specified type that can be used in a constructor, and in other contexts. You can construct an initializer_list by using brace initialization:

docs/cpp/templates-cpp.md

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Templates (C++)"
3-
ms.date: "11/04/2016"
3+
ms.date: "12/27/2019"
44
f1_keywords: ["template_cpp"]
55
helpviewer_keywords: ["templates, C++", "templates [C++]"]
66
ms.assetid: 90fcc14a-2092-47af-9d2e-dba26d25b872
@@ -74,7 +74,7 @@ vtclass<int> vtinstance2;
7474
vtclass<float, bool> vtinstance3;
7575
```
7676

77-
Any built-in or user-defined type can be used as a type argument. For example, you can use std::vector in the Standard Library to store ints, doubles, strings, MyClass, const MyClass*, MyClass&. The primary restriction when using templates is that a type argument must support any operations that are applied to the type parameters. For example, if we call minimum using MyClass as in this example:
77+
Any built-in or user-defined type can be used as a type argument. For example, you can use [std::vector](../standard-library/vector-class.md) in the Standard Library to store variables of type **int**, **double**, [std::string](../standard-library/basic-string-class.md), `MyClass`, **const** `MyClass`*, `MyClass&`, and so on. The primary restriction when using templates is that a type argument must support any operations that are applied to the type parameters. For example, if we call `minimum` using `MyClass` as in this example:
7878

7979
```cpp
8080
class MyClass
@@ -92,7 +92,7 @@ int main()
9292
}
9393
```
9494

95-
A compiler error will be generated because MyClass does not provide an overload for the < operator.
95+
A compiler error will be generated because `MyClass` does not provide an overload for the **<** operator.
9696

9797
There is no inherent requirement that the type arguments for any particular template all belong to the same object hierarchy, although you can define a template that enforces such a restriction. You can combine object-oriented techniques with templates; for example, you can store a Derived* in a vector\<Base\*>. Note that the arguments must be pointers
9898

@@ -106,11 +106,11 @@ vector<MyClass*> vec;
106106
vec2.push_back(make_shared<MyDerived>());
107107
```
108108
109-
The basic requirements that vector and other standard library containers impose on elements of `T` is that `T` be copy-assignable and copy-constructible.
109+
The basic requirements that `std::vector` and other standard library containers impose on elements of `T` is that `T` be copy-assignable and copy-constructible.
110110
111111
## Non-type parameters
112112
113-
Unlike generic types in other languages such as C# and Java, C++ templates support non-type parameters, also called value parameters. For example, you can provide a constant integral value to specify the length of an array, as with this example that is similar to the std::array class in the Standard Library:
113+
Unlike generic types in other languages such as C# and Java, C++ templates support *non-type parameters*, also called value parameters. For example, you can provide a constant integral value to specify the length of an array, as with this example that is similar to the [std::array](../standard-library/array-class-stl.md) class in the Standard Library:
114114
115115
```cpp
116116
template<typename T, size_t L>
@@ -122,14 +122,26 @@ public:
122122
};
123123
```
124124

125-
Note the syntax in the template declaration. The size_t value is passed in as a template argument at compile time and must be constant or a constexpr expression. You use it like this:
125+
Note the syntax in the template declaration. The `size_t` value is passed in as a template argument at compile time and must be **const** or a **constexpr** expression. You use it like this:
126126

127127
```cpp
128128
MyArray<MyClass*, 10> arr;
129129
```
130130

131131
Other kinds of values including pointers and references can be passed in as non-type parameters. For example, you can pass in a pointer to a function or function object to customize some operation inside the template code.
132132

133+
### Type deduction for non-type template parameters
134+
135+
In Visual Studio 2017 and later, in **/std:c++17** mode the compiler deduces the type of a non-type template argument that is declared with **auto**:
136+
137+
```cpp
138+
template <auto x> constexpr auto constant = x;
139+
140+
auto v1 = constant<5>; // v1 == 5, decltype(v1) is int
141+
auto v2 = constant<true>; // v2 == true, decltype(v2) is bool
142+
auto v3 = constant<'a'>; // v3 == 'a', decltype(v3) is char
143+
```
144+
133145
## <a id="template_parameters"></a> Templates as template parameters
134146

135147
A template can be a template parameter. In this example, MyClass2 has two template parameters: a typename parameter *T* and a template parameter *Arr*:

docs/overview/cpp-conformance-improvements.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,46 +1235,38 @@ For more information, see [Constructors](../cpp/constructors-cpp.md#inheriting_c
12351235
12361236
[P0017R1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0017r1.html)
12371237
1238-
If the constructor of a base class is non-public, but accessible to a derived class, then under **/std:c++17** mode in Visual Studio version 15.7 you can no longer use empty braces to initialize an object of the derived type.
1239-
1238+
If the constructor of a base class is non-public, but accessible to a derived class, then under **/std:c++17** mode in Visual Studio 2017 version 15.7 you can no longer use empty braces to initialize an object of the derived type.
12401239
The following example shows C++14 conformant behavior:
12411240
12421241
```cpp
12431242
struct Derived;
1244-
12451243
struct Base {
12461244
friend struct Derived;
12471245
private:
12481246
Base() {}
12491247
};
12501248
12511249
struct Derived : Base {};
1252-
12531250
Derived d1; // OK. No aggregate init involved.
12541251
Derived d2 {}; // OK in C++14: Calls Derived::Derived()
12551252
// which can call Base ctor.
12561253
```
12571254

12581255
In C++17, `Derived` is now considered an aggregate type. It means that the initialization of `Base` via the private default constructor happens directly, as part of the extended aggregate initialization rule. Previously, the `Base` private constructor was called via the `Derived` constructor, and it succeeded because of the friend declaration.
1259-
12601256
The following example shows C++17 behavior in Visual Studio version 15.7 in **/std:c++17** mode:
12611257

12621258
```cpp
12631259
struct Derived;
1264-
12651260
struct Base {
12661261
friend struct Derived;
12671262
private:
12681263
Base() {}
12691264
};
1270-
12711265
struct Derived : Base {
12721266
Derived() {} // add user-defined constructor
12731267
// to call with {} initialization
12741268
};
1275-
12761269
Derived d1; // OK. No aggregate init involved.
1277-
12781270
Derived d2 {}; // error C2248: 'Base::Base': cannot access
12791271
// private member declared in class 'Base'
12801272
```

0 commit comments

Comments
 (0)