Doc. No.: | N4433 |
---|---|
Date: | 2014-04-09 |
Project: | Programming Language C++, Evolution Working Group |
Reply To: | Michael Price <michael.b.price.dev@gmail.com> |
static_assert
messages
Currently, the specification for static_assert
has two forms,
one that takes a string-literal that is used as a diagnostic
message and another that takes no diagnostic message at all. The
restriction that the diagnostic message be a string-literal is
limiting since it doesn't allow useful contextual information to be
inserted into the diagnostic message. This paper proposes that we change
the specification to take a constant expression that can be contextually
converted to a const char*
, const wchar_t*
,
const char16_t*
, or const char32_t*
instead of a
string-literal.
As a library developer, I'd like to include information in diagnostic messages that indicate that my library was the source of the assertion. With the current specification, this becomes an error-prone exercise. If I were required to "rebrand" my library, it's even worse. With the proposed changes, it's a matter of changing a single line in a header file.
// mplib.h
//
constexpr auto libraryTag = "MP"S; // Presumes a UDL for compile-time string literals
// (see N4121 [2])
template <typename C, typename M>
constexpr auto msg (C errorCode, M message)
{
return libraryTag + errorCode + ": "S + message;
}
// mpsource1.cpp
//
#include "mplib.h"
// ...
static_assert(sizeof(int) == 32, msg("001"S, "Requires type 'int' to be 32 bits"S));
// mpsource8534.cpp
//
#include "mplib.h"
// ...
static_assert(std::is_integral<T>::value, msg("999"S, "T must be an integral type"S);
Another use case of such an extension would be to allow type-dependent or implementation-specific information to appear in the diagnostic message.
// Assume some compile-time formatter function with the following syntax
//
template <typename M, typename Ts...>
constexpr auto format (const M& message, Ts... ts);
template <typename T, std::size_t N>
struct limited_buffer {
unsigned char data[16];
static_assert(sizeof(T) * N <= sizeof(data),
format("You can only fit {0} {1}s into a {2}."S,
sizeof(data)/sizeof(T),
typeid(T)::name(), // Assuming this were constexpr
"limited_buffer"S
)
);
};
All edits are against N4140 [1]
Edit paragraph 7.1 [dcl.dcl] as follows.
static_assert-declaration:
static_assert (
constant-expressionconstant-expression-test ) ;
static_assert (
constant-expressionconstant-expression-test ,string-literalconstant-expression-message ) ;
Edit paragraph 7.1.6 as follows.
In a static_assert-declaration the
constant-expressionconstant-expression-test shall be a constant expression (5.20) that can be contextually converted tobool
(Clause 4) , and the constant-expression-message shall be a constant expression (5.20) that can be contextually converted toconst char*
,const wchar_t*
,const char16_t*
, orconst char32_t*
(Clause 4). If the value ofthe expressionconstant-expression-test when so converted istrue
, the declaration has no effect. Otherwise, the program is ill-formed, and the resulting diagnostic message (1.4) shall include thetext of the string-literalvalue of constant-expression-message after conversion, if one is supplied, except that characters not in the basic source character set (2.3) are not required to appear in the diagnostic message. [ Example:— end example ]static_assert(sizeof(long) >= 8, "64-bit code generation required for this library.");
static_assert
fires during the
evaluation of the constant-expression-message?
A: Implementation defined behavior.
The current text does not specify what happens if a static_assert
fires during the evaluation of the expression being tested. Admittedly,
choosing a behavior might be more complicated in this case, but it should
still be at the discretion of the implementation.
const wchar_t*
, etc...)?
A: Because the grammer for the existing string-literal parameter does.
See [lex.string] [1].
I would hardly have the time to author these proposals were it not for the generosity of my employer, Lexmark International, who has earned my thanks for their continuing support. I also wanted to extend my gratitude to those individuals who carefully reviewed this paper and provided valuable feedback, Chris Sammis, Ryan Lucchese, and John Drouhard.