This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 15.1.5 - A class shall only define an initializer-list constructor when it is the only constructor
[dcl.init.list]
Category: Required
Analysis: Decidable,Single Translation Unit
Amplification
Copy and move constructors are permitted in addition to the initializer-list constructor.
A constructor is an initializer-list constructor if:
- Its first parameter is of type
std::initializer_list< T > or is a reference to a (possibly cv-qualified)
std::initializer_list< T >, and
- Either there are no other parameters or else all other parameters have default arguments.
Rationale
Under the special overload resolution rules, a constructor with a sole std::initializer_list< T > parameter will always be
preferred over a constructor taking individual arguments of convertible types in initializations using curly braces. Consequently, the effect of an
initialization may differ depending on the form of initialization (curly braces or parentheses) and may not meet developer expectation.
Although the guidelines within this document do not apply to C++ Standard Library definitions, the design of std::vector demonstrates
the problem that this rule prevents in user classes:
std::vector< int32_t > v1{ 3, 4 }; // Vector has two elements: {3, 4}
std::vector< int32_t > v2( 3, 4 ); // Vector has three elements: {4, 4, 4}
Another source of confusion arises when a default constructor is present and an object is initialized with empty curly braces. According to
language rules, this will always call the default constructor, but a developer may expect an initialization with an empty initializer list.
Note: a non-constructor function taking a single std::initializer_list< T > parameter will require both
parentheses and curly braces at the call site, so does not suffer from the concern addressed by this rule.
Example
class A // Non-compliant
{
public:
A( std::size_t x, std::size_t y );
A( std::initializer_list< std::size_t > list );
};
class B // Compliant - no initializer-list constructor
{
public:
B( std::size_t x, std::size_t y );
// The following is not an initializer-list constructor
B( std::size_t x, std::initializer_list< std::size_t > list);
};
class C // Compliant
{
public:
C( std::initializer_list< std::size_t > list );
};
class D // Compliant
{
public:
D( const D & d );
D( D && d );
D( std::initializer_list< std::size_t > list );
};
Copyright The MISRA Consortium Limited © 2023