You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In compliance with the *meta.rqmts* subclause of the Standard, the MSVC compiler now raises an error when it encounters a user-defined specialization of one of the specified type_traits templates in the `std` namespace. Unless otherwise specified, such specializations result in undefined behavior. The following example has undefined behavior because it violates the rule, and the `static_assert` fails with error **C2338**.
568
+
In compliance with the *meta.rqmts* subclause of the Standard, the MSVC compiler now raises an error when it encounters a user-defined specialization of one of the specified `type_traits` templates in the `std` namespace. Unless otherwise specified, such specializations result in undefined behavior. The following example has undefined behavior because it violates the rule, and the `static_assert` fails with error **C2338**.
The MSVC compiler now implements the following changes to comparison operators per [P1630R1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1630r1.html) when the [/std:c++latest](../build/reference/std-specify-language-standard-version.md) option is enabled:
599
599
600
-
The compiler will no longer rewrite expressions with `operator==` if they involve a return type that is not a **bool**. The following code now produces *error C2088: '!=': illegal for struct*:
600
+
The compiler no longer rewrites expressions using `operator==` if they involve a return type that isn't a **bool**. The following code now produces *error C2088: '!=': illegal for struct*:
The compiler will no longer define a defaulted comparison operator if it is a member of a union-like class. The following example now produces *C2120: 'void' illegal with all types*:
633
+
The compiler no longer defines a defaulted comparison operator if it's a member of a union-like class. The following example now produces *C2120: 'void' illegal with all types*:
## <a name="improvements_165"></a> Conformance improvements in Visual Studio 2019 version 16.5
696
+
697
+
### Explicit specialization declaration without an initializer is not a definition
698
+
699
+
Under `/permissive-`, MSVC now enforces a standard rule that explicit specialization declarations without initializers aren't definitions. Previously, the declaration would be considered a definition with a default-initializer. The effect is observable at link time, since a program depending on this behavior may now have unresolved symbols. This example now results in an error:
700
+
701
+
```cpp
702
+
template <typename> struct S {
703
+
static int a;
704
+
};
705
+
706
+
// In permissive-, this declaration is not a definition and the program will not link.
707
+
template <> int S<char>::a;
708
+
709
+
int main() {
710
+
return S<char>::a;
711
+
}
712
+
```
713
+
714
+
```Output
715
+
error LNK2019: unresolved external symbol "public: static int S<char>::a" (?a@?$S@D@@2HA) referenced in function _main
716
+
at link time.
717
+
```
718
+
719
+
To resolve the issue, add an initializer:
720
+
721
+
```cpp
722
+
template <typename> structS {
723
+
static int a;
724
+
};
725
+
726
+
// Add an initializer for the declaration to be a definition.
727
+
template <> int S<char>::a{};
728
+
729
+
int main() {
730
+
return S<char>::a;
731
+
}
732
+
```
733
+
734
+
### Preprocessor output preserves newlines
735
+
736
+
The experimental preprocessor now preserves newlines and whitespace when using `/P` or `/E` with `/experimental:preprocessor`. This change can be disabled by using `/d1experimental:preprocessor:oldWhitespace`.
737
+
738
+
Given this example source,
739
+
740
+
```cpp
741
+
#define m()
742
+
line m(
743
+
) line
744
+
```
745
+
746
+
The previous output of `/E` was:
747
+
748
+
```Output
749
+
line line
750
+
#line 2
751
+
```
752
+
753
+
The new output of `/E` is now:
754
+
755
+
```Output
756
+
line
757
+
line
758
+
```
759
+
760
+
### 'import' and 'module' keywords are context dependent
761
+
762
+
Per P1857R1, import and module preprocessor directives have additional restrictions on their syntax. This example no longer compiles:
763
+
764
+
```cpp
765
+
import// Invalid
766
+
m;
767
+
```
768
+
769
+
It produces the following error message:
770
+
771
+
```Output
772
+
error C2146: syntax error: missing ';' before identifier 'm'
773
+
```
774
+
775
+
To resolve the issue, keep the import on the same line:
776
+
777
+
```cpp
778
+
import m; // OK
779
+
```
780
+
781
+
### Removal of std::weak_equality and std::strong_equality
782
+
783
+
The merge of P1959R0 requires the compiler to remove behavior and references to the `std::weak_equality` and `std::strong_equality` types.
nullptr != nullptr; // use pre-existing builtin operator != or ==.
824
+
&f != &f;
825
+
&S::operator<=> != &S::operator<=>;
826
+
}
827
+
```
828
+
829
+
### TLS Guard changes
830
+
831
+
Previously, thread-local variables in DLLs weren't correctly initialized before their first use on threads
832
+
that existed before the DLL was loaded, other than the thread that loaded the DLL. This defect has now been corrected.
833
+
Thread-local variables in such a DLL are initialized immediately before their first use on such threads.
834
+
835
+
This new behavior of testing for initialization on uses of thread-local variables may be disabled by using the
836
+
`/Zc:tlsGuards-` compiler switch. Or, by adding the `[[msvc:no_tls_guard]]` attribute to particular thread local variables.
837
+
838
+
### Better diagnosis of call to deleted functions
839
+
840
+
Our compiler was more permissive about calls to deleted functions previously. For example, if the calls happened in the context of a template body, we wouldn't diagnose the call. Additionally, if there were multiple instances of calls to deleted functions, we would only issue one diagnostic. Now we issue a diagnostic for each of them.
841
+
842
+
One consequence of the new behavior can produce a small breaking change: Code that called a deleted function wouldn't get diagnosed if it was never needed for code generation. Now we diagnose it up front.
843
+
844
+
This example shows code that now produces an error:
845
+
846
+
```cpp
847
+
struct S {
848
+
S() = delete;
849
+
S(int) { }
850
+
};
851
+
852
+
struct U {
853
+
U() = delete;
854
+
U(int i): s{ i } { }
855
+
856
+
S s{};
857
+
};
858
+
859
+
U u{ 0 };
860
+
```
861
+
862
+
```Output
863
+
error C2280: 'S::S(void)': attempting to reference a deleted function
864
+
note: see declaration of 'S::S'
865
+
note: 'S::S(void)': function was explicitly deleted
866
+
```
867
+
868
+
To resolve the issue, remove calls to deleted functions:
869
+
870
+
```cpp
871
+
structS {
872
+
S() = delete;
873
+
S(int) { }
874
+
};
875
+
876
+
struct U {
877
+
U() = delete;
878
+
U(int i): s{ i } { }
879
+
880
+
S s; // Do not call the deleted ctor of 'S'.
881
+
};
882
+
883
+
U u{ 0 };
884
+
```
885
+
695
886
## <a name="update_160"></a> Bug fixes and behavior changes in Visual Studio 2019
0 commit comments