0

Here is the simplest code I can give:

// main.cpp
#include "test.h"

int main() { return 0; }
// test.h
#pragma once
#include <cstring>

const char str[] = "ABCD";

template <
    const char* str,
    std::size_t N
>
class A {};

class B : public A<str, strlen(str)> {};
// test.cpp
#include "test.h"

When I compile, I get twice the following warning:

test.h:13:7: warning: ‘B’ has a base ‘A<(& str), 4>’ whose type uses the anonymous namespace [-Wsubobject-linkage]
   13 | class B : public A<str, strlen(str)> {};
      |       ^

The reason why I get it twice is because test.h is included twice, once in main.cpp and once in test.cpp.

A similar question has already been answering in this post, but there was only a const char* and not a std::size_t too.

The answer of the above linked post was to use the extern keyword before const char str[] and define str in the test.cpp. But with std::size_t the compilation with the corrected code gives the following error:

test.h:13:31: error: ‘strlen(((const char*)(& str)))’ is not a constant expression
   13 | class B : public A<str, strlen(str)> {};
      |                         ~~~~~~^~~~~

Of course my code is more complicated than that and the main problem is that my object only need a const char*, the strlen(str) is done by another templated class far behind.

How can I do things to not have warnings or errors?

Ephesiel
  • 119
  • 9

1 Answers1

1

std::strlen() can't be used in a constexpr context. You can use std::size(). Also you need to make str array inline for letting the compiler know str array size.

inline const char str[] = "ABCD";

lass B : public A<str, std::size(str) - 1> {};
273K
  • 29,503
  • 10
  • 41
  • 64
  • with this I get the following error : `error: invalid use of array with unspecified bounds 246 | -> decltype(__cont.size())`, are you sure it works with `const char*`? – Ephesiel Aug 18 '23 at 17:41
  • 1
    @Ephesiel: Do you have `extern const char str[5];`? – Jarod42 Aug 18 '23 at 17:45
  • Got it, the answer is updated. – 273K Aug 18 '23 at 17:46
  • Okay, it works if I specify the length of the string in the brackets. `extern const char str[5]`. I also find in [this post](https://stackoverflow.com/questions/72801432/why-do-i-get-the-child-has-a-base-whose-type-uses-the-anonymous-namespace-warn) that the `inline` keyword worked in my case. Thanks. – Ephesiel Aug 18 '23 at 17:46
  • *"GCC (and other compilers) treat `strlen` as a 'constexpr' function as an extension to the language."* That might make OP code working. – Jarod42 Aug 18 '23 at 17:47