rspec/rules/S5829/cfamily/rule.adoc

130 lines
3.0 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

== Why is this an issue?
C+11 introduced “Uniform initialization”/"list initialization". It is a way to initialize an object from a braced-init-list. This adds a third way to initialize objects in {cpp} on top of parentheses and equal signs.
----
int a{1}; // braces initialization
int b(1); // parentheses initialization
int c=1; // equal sign initialization
----
“Uniform initialization” was introduced to address the confusion of the many initialization syntaxes in {cpp} and to give a syntax that, in concept, can be used in all initialization scenarios. It helps to:
* Initialize container in a way that wasn't possible before:
----
// Before
std::vector<int> v;
v.push_back(1);
v.push_back(2);
// After
std::vector<int>{1,2,3};
----
* Avoid narrowing:
----
double d=2.5;
int i{d}; // Compilation error
----
* Avoid the most vexing parse:
----
class A{};
A a(); // Compilation error declares a function named a that returns A.
A a{}; // Call A constructor
----
That is why “Uniform initialization” should be preferred.
=== Noncompliant code example
[source,cpp]
----
struct A {
A(int i, int j, int z) {
...
}
};
void f() {
A a(1,2,3); // Noncompliant
}
struct B {
A a = A(1, 2, 3); // Noncompliant
};
----
=== Compliant solution
[source,cpp]
----
struct A {
A(int i, int j, int z) {
...
}
};
void f() {
A a{1,2,3};
}
struct B {
A a{1, 2, 3};
};
----
=== Exceptions
* In some situations, “Uniform initialization” has surprising behavior. for example, in constructor overload resolution, “Uniform initialization” prefers the constructor with "std::initializer_list" as a parameter if possible, even if another constructor seems like a better match. Like in the "std::vector" case, you might need to go back to parentheses in order to call the non "intializer_list" constructor:
[source,cpp]
----
vector<int> v1(5, 10); // 5 copies of the value 10
----
* When "=" is after "auto". This might be needed to enforce deduction to initializer_list: 
[source,cpp]
----
auto i1 {1}; // int with the value 1
auto i2 = {1}; // std::initializer_list<int> with an element equal to 1
----
* In single argument cases, "=" is okay:
[source,cpp]
----
int i = 39;
----
* When the braces are after the "=":
[source,cpp]
----
vector<int> v = { 1, 2, 4 };
----
== Resources
* {cpp} Core Guidelines - https://github.com/isocpp/CppCoreGuidelines/blob/e49158a/CppCoreGuidelines.md#es23-prefer-the\--initializer-syntax[ES.23: Prefer the `{}`-initializer syntax]
ifdef::env-github,rspecator-view[]
'''
== Comments And Links
(visible only on this page)
=== on 11 May 2020, 09:05:55 Geoffray Adde wrote:
* The description is crystal clear! I love the summary about initialization.
* In single argument cases, "=" is okay:  =>  maybe builtin single argument case ?
* In some situations, “Uniform initialization” has surprising behavior. => somehow to me, it makes sense because the curly braces syntax seems to indicate initializer list.
* Do we need more examples?
endif::env-github,rspecator-view[]