Rule A17-1-1 (required, implementation, non-automated)

Use of the C Standard Library shall be encapsulated and isolated.

Rationale

The C Standard Library leaves the responsibility for handling errors, data races and security concerns up to developers. Therefore, use of the C Standard Library needs to be separated and wrapped with functions that will be fully responsible for all specific checks and error handling.

Example

// $Id: A17-1-1.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdexcept>

void Fn1(const char* filename) // Compliant - C code is isolated; fn1()

// function is a wrapper.

{
FILE* handle = fopen(filename, "rb");

if (handle == NULL)
{
throw std::system_error(errno, std::system_category());
}
// ...
fclose(handle);

}

void Fn2() noexcept
{
try
{
Fn1("filename.txt"); // Compliant - fn1() allows you to use C code like
// C++ code

// ...
}
catch (std::system_error& e)
{
std::cerr << "Error: " << e.code() << " - " << e.what() << ā€™\nā€™;
}
}

std::int32_t Fn3(const char* filename) noexcept // Non-compliant - placing C

// functions calls along with C++
// code forces a developer to be
// responsible for C-specific error
// handling, explicit resource
// cleanup, etc.
{
FILE* handle = fopen(filename, "rb");

if (handle == NULL)
{
std::cerr << "An error occured: " << errno << " - " << strerror(errno)
<< ā€™\nā€™;
return errno;
}

try
{
// ...
fclose(handle);
}
catch (std::system_error& e)
{
fclose(handle);
}
catch (std::exception& e)
{
fclose(handle);
}

return errno;
}

See also

MISRA C++ 2008 [7]: Rule 19-3-1 The error indicator errno shall not be used.

HIC++ v4.0 [9]: 17.2.1 Wrap use of the C Standard Library. JSF December 2005 [8]: Chapter 4.5.1: Standard Libraries, AV Rule 17 - AV Rule 25.

The corresponding section in the C++14 standard provides a glossary only.

Rule A17-6-1 (required, implementation, automated) Non-standard entities shall not be added to standard namespaces.

Rationale

Adding declarations or definitions to namespace std or its sub-namespaces, or to namespace posix or its sub-namespaces leads to undefined behavior. Declaring an explicit specialization of a member function or member function template of a standard library class or class template leads to undefined behavior. Declaring an explicit or partial specialization of a member class template of a standard library class or class template leads to undefined behavior.

Exception

It is allowed by the language standard to add a specialization to namespace std if the declaration depends on a user-defined type, meets the requirements for the original template and is not explicitly forbidden. It is allowed by the language standard to explicitly instantiate a template defined in the standard library if the declaration depends on a user defined type and meets the requirements for the original template.

Example

// $Id: A17-6-1.cpp 305588 2018-01-29 11:07:35Z michal.szczepankiewicz $
#include <cstdint>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>

namespace std
{

// Non-compliant - An alias definition is added to namespace std.

// This is a compile error in C++17, since std::byte is already defined.
using byte = std::uint8_t;

// Non-compliant - A function definition added to namespace std.
pair<int, int> operator+(pair<int, int> const& x, pair<int, int> const& y)
{
return pair<int, int>(x.first + y.first, x.second + y.second);
}

} // namespace std

struct MyType
{
int value;
};

namespace std
{

// Non-compliant - std::numeric_limits may not be specialized for
// non-arithmetic types [limits.numeric].
template <>
struct numeric_limits<MyType> : numeric_limits<int>
{
};

// Non-compliant - Structures in <type_traits>, except for std::common_type,
// may not be specialized [meta.type.synop].
template <>
struct is_arithmetic<MyType> : true_type
{
};

// Compliant - std::hash may be specialized for a user type if the
// specialization fulfills the requirements in [unord.hash].
template <>
struct hash<MyType>
{
using result_type = size_t;
// deprecated in C++17
using argument_type = MyType; // deprecated in C++17

size_t operator()(MyType const& x) const noexcept
{
return hash<int>()(x.value);
}
};

} // namespace std

See also

SEI CERT C++ Coding Standard [10]: DCL58-CPP: Do not modify the standard namespaces C++ Core Guidelines [11]: SL.3: Do not add non-standard entities to namespace std ISO/IEC 14882:2014 [3]: 17.6.4.2: [namespace.constraints] ISO/IEC 14882:2014 [3]: 18.3.2.1: [limits.numeric] ISO/IEC 14882:2014 [3]: 20.9.13: [unord.hash] ISO/IEC 14882:2014 [3]: 20.10.2: [meta.type.synop]

The corresponding chapter in the C++ standard defines the fundamental support libraries, including integer types, dynamic memory, start and termination.