Hi
I have some c++ code with a class that use some constant strings and has these as members.
class CLMyTest
{
enum ENKeywords
{
eKey1,
eKey2,
eKeySize
};
// Original way
static constexpr const wchar_t* const origKeywords[]{
L"KEY_1" ,
L"KEY_2"
};
static_assert(_countof( origKeywords ) == eKeySize, "origKeywords must be updated");
// Sonar way
static constexpr std::array<const wchar_t*, eKeySize> newKeywords = {
L"KEY_1" ,
L"KEY_2"
};
static_assert(newKeywords.size() == eKeySize, "newKeywords must be updated"); // Will not work
};
The original code will raise issue cpp:S5945.
But if I change the code to the Sonar way I do not have the option to validate that the enum and the array have the same length at compile time.
I know I can make an runtime check but compared to the previous solution this is not as nice in my opinion.
It may of cause be that there is some other way to do this but I have not be able to find a way that preserves the performance and maintains the simplicity.
Basically I just need to maintain constant strings in an array that I can loop over and acces with something like Func( origKeywords[eKey1] ).
I use SonarQube Server Enterprise Edition v10.7 and Visual studio IDE Version: 8.9.0.11507.
Thanks for bringing this example up for discussion.
I wonder, what makes you think that the “Sonar way” using static_assert(newKeywords.size() == eKeySize, "newKeywords must be updated"); // Will not work? The function member std::array::size() is declared as constexpr and can be used in static_assert.
I’ve crafted the following Compiler Explorer; please give it a check.
Thanks for the reply.
If you try adding “, eKey3” to the enum you only get an error in the original code.
This is because the newKeywords.size() will be the eKeySize regardless of the number of elements defined in the std::array.
Where the original code could use _countof to validate against.
Maybe there is another way to do this ?
While the solution suggested by @pdschbrt works well, it comes with one caveat that may or may not be an issue for you: With CTAD & std::array, you can omit both template arguments, but there is no way to specify the type and omit the size.
In case you want to do so, you’ll have to use a helper function. C++20 provides std::to_array, but even before that, you can write your own (see the link for a possible implementation).