Array of constant strings

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 Kennet

Hey @Kennet!

Can you tell us what version you’re using?

Specifically for SonarQube Server, you’ll find this info in the footer of your instance.

I have update the original post with this.

Hi @Kennet,

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.

Best,
Philipp

Hi @pdschbrt

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 ?

@Kennet,

Thanks for providing this additional description, I got it now.

How about using C++17 std::array class template argument deduction (CTAD) such that array initialization becomes:

static constexpr std::array newKeywords = {L"KEY_1", L"KEY_2"};

This way, the second static_assert will trigger, too, if you add eKey3, for instance.

Philipp

Thanks did not know about CTAD

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).

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.