We use the following macro to declare a class non-copyable:
/** Macro to make a class non-copyable */
#define CLASS_DECLARE_NON_COPYABLE(className) \
className(const className&) = delete;\
className& operator= (const className&) = delete;
Rule [cpp:S963] says: In the definition of a function-like macro, each instance of a parameter shall be enclosed in parentheses, unless it is used as the operand of # or ##
To my knowledge, there’s no (reasonable) way to write this with the parameter in parentheses (suggestions welcome).
Call this “preprocessor abuse” or “bad style” if you want, but it’s definitely not a ‘function-style macro’ in the strict sense, so I’m reporting this as a false positive.
SonarQube server 8.9.0, SonarScanner 4.6.1.2450, sonar.cfamily
You are right that such a macro cannot be written with parentheses. But it is still a function-like macro, as defined by MISRA, and your code is therefore not compliant according to MISRA-C++2008. If this is something that you care about, you would have to deviate from the rule, or find another mechanism than a macro for this (which might be a good idea, see later for some options). If you don’t have to conform to MISRA, you may still use another mechanism, or just ignore this issue.
We have in mind to write a non MISRA version of this rule that would be less strict. At the same time, MISRA is revisiting its rules, and your case would not be in violation in the new version (which I cannot disclose yet).
Here are two macro-less alternatives to make a class non-copyable and non-assignable without too much typing:
class MyClass {
public:
// some stuff
void operator=(MyClass&&) = delete;
};
Or an alternative that might state the intent more clearly:
class NonCopyable {
void operator=(NonCopyable &&) = delete;
// Or use the version where you delete copy ctor and copy assignement operator
};
class MyClass {
NonCopyable nonCopyable;
// Other stuff
};
// Or
class MyClass : NonCopyable { // Allows empty base class optimization
// Other stuff
}
I will take this opportunity to remove this macro from my codebase altogether.
I was indeed not familiar with the rule of DesDeMovA as such, that lightning talk summarizes it very nicely.
addendum: using the composition method for your suggested NonCopyable class might trigger warnings for “unused field” which might need to be additionally silenced. Therefore, I prefer the inheritance variant.