Currently, I have the following piece of code:
enum class Letters {
A,
B,
C
};
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
Letters e(Letters::A);
switch(e){
case Letters::A: break;
case Letters::B: break;
}
#pragma GCC diagnostic pop
I want to use something like this:
class DiagnosticError {
public:
constexpr DiagnosticError() {
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wswitch"
}
constexpr ~DiagnosticError() {
#pragma GCC diagnostic pop
}
};
enum class Letters {
A,
B,
C
};
{
constexpr DiagnosticError switchError;
Letters e(Letters::A);
switch(e){
case Letters::A: break;
case Letters::B: break;
}
}
The code compiles fine under C++20, but without generating the error:
error: enumeration value 'C' not handled in switch [-Werror=switch]
38 | switch(e){
Why is that? Is it possible to achieve what I want?
Pragmas are handled by too early a translation phase to apply something like a guard object to a block. The best you can do is write your macros to cut a bit on the boiler-plate
#define DIAG_ERR_PUSH(flags) _Pragma("GCC diagnostic push") DIAG_ERR_PUSH_(GCC diagnostic error flags)
#define DIAG_ERR_PUSH_(str) _Pragma(#str)
#define DIAG_POP() _Pragma("GCC diagnostic pop")
enum class Letters {
A,
B,
C
};
DIAG_ERR_PUSH("-Wswitch")
Letters e(Letters::A);
switch(e){
case Letters::A: break;
case Letters::B: break;
}
DIAG_POP()
Since C++11 we have the _Pragma
form of the directive, to embed pragmas into other expansions. DIAG_ERR_PUSH(...)
takes the place of your guard object, and DIAG_POP()
delimits the region (instead of curly braces).
Not quite RAII, but sure better than having to type all the minutia for the pragma. Here's a live example.