1

I have a function like this:

void column(const std::string &value) { ... }

void column(float value) { ... }

template <class... TColumns> void row(const TColumns &...columns) {
  ImGui::TableNextRow();
  (column(columns), ...);
}

I am using clang-tidy static analyzer to make sure that my code is always compliant with cpp core guidelines. I am using this function in the following way:

// (const char[5], float)
row("Hello", 20.5f);

My understanding is that, std:string accepts const char * but the first argument of the function call above gets inferred to const char[5]. This causes array decay and I get clang-tidy error that:

do not implicitly decay an array into a pointer; consider using gsl::array_view or an explicit cast instead

Is it possible to somehow enforce that string argument that is passed is always const char *, not const char[5] or const char[6] etc?

Gasim
  • 7,615
  • 14
  • 64
  • 131
  • 6
    How about turning off this warning? Any solution provided here will be inferior to simply writing what you mean. Coding standards should always be used with caution and common sense. – lorro Aug 08 '22 at 20:21
  • Also, make it a `static const std::string hello = "Hello";` if you use it multiple times... or simply take a `string_view` in `column` if you don't need ownership. – lorro Aug 08 '22 at 20:23
  • _A string literal is a `const char[]` in C++_ https://stackoverflow.com/questions/8356223/assign-a-string-literal-to-a-char – no more sigsegv Aug 08 '22 at 20:24
  • The type of `"Hello"` is `const char[6]`. If you want a different type deduced, you'd need to specify what that type is. – NathanOliver Aug 08 '22 at 20:25
  • Does this answer your question? ['Clang-Tidy: Do not implicitly decay an array into a pointer' when using std::forward and const char\*](https://stackoverflow.com/questions/72101801/clang-tidy-do-not-implicitly-decay-an-array-into-a-pointer-when-using-stdfo) – lorro Aug 08 '22 at 20:26
  • 1
    You could add a `template void column(const (&value)[N])` overload to work with string literals directly and not convert them to a `std::string` which might do a dynamic allocation. – NathanOliver Aug 08 '22 at 20:27
  • @NathanOliver Is there a way to decay this from character array to character pointer? The thing is, in the implementation of a function, I am using a funciton that accepts `const char *`. So, I can‘t directly use that either. – Gasim Aug 08 '22 at 20:31
  • You would have to do an explicit cast like `static_cast("hello")` – NathanOliver Aug 08 '22 at 20:36
  • You could use Nathan's suggestion to forward the C string literal to the std::string function: `template void column(const (&value)[N]) { column(std::string(value)); }` – Eljay Aug 08 '22 at 20:37
  • 2
    You could also add `// NOLINT` to the end of the line to disable clang-tidy warnings on that line. Although i agree that this warning should be disabled. – Drew Dormann Aug 08 '22 at 20:40
  • @Iorro I like having the warnings for other cases where decaying matters but it has drawbacks like character arrays complaining about array decay. So, I just disabled it for this particular line without needing to disable it globally. – Gasim Aug 08 '22 at 20:54
  • Another option is to use `using namespace std::string_literals; row("Hello"s, 20.5f);` and now `"Hello"s` is a `std::string` literal – NathanOliver Aug 08 '22 at 20:59

1 Answers1

1

Since you anyways convert a c-string to a string each time you reach this line, it's suggested to have a static string. That is expected to solve the warning as well.

#include <iostream>

void column(const std::string &value) { }
void column(float value) { }

template <class... TColumns> void row(const TColumns &...columns) {
  // ...
  (column(columns), ...);
}

int main() {
    static auto hello = std::string{"Hello"};
    row(hello, 20.5f);
}

However, the best solution is likely to simply turn off the warning - either globally, or as Drew wrote, via // NOLINT.

lorro
  • 10,687
  • 23
  • 36