Can a constexpr c-string used as template parameter be instantiated in a template function?

Viewed 69

I have been prototyping a library in which I would like to use a c-string value defined locally in a function as a non-type template parameter.

In essence, the bare minimum implementation is the following (see on godbolt):

#include <cstdio>
#include <type_traits>

template <char const* C>
class compile_string {};

template <typename T>
auto foo() {
    static constexpr char const CSTR[] = "Hello, World!";

    return compile_string<CSTR>{};
}

int main() {
    auto shorty = foo<short>();
    auto inty = foo<int>();

    return std::is_same_v<decltype(shorty), decltype(inty)>;
}

When compiling this short program with the latest clang (11.0), in O1 to O3 everything works well, however when compiling with O0, linking fails.

Despite the assembly section containing:

; foo<short>()::CSTR
_ZZ3fooIsEDavE4CSTR:
        .asciz  "Hello, World!"

; foo<int>()::CSTR
_ZZ3fooIiEDavE4CSTR:
        .asciz  "Hello, World!"

There is a linker error:

/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/example-a4bb3b.o:(.debug_info+0x1be): undefined reference to `foo()::CSTR'

Passing -Xlinker --no-demangle this error becomes:

/opt/compiler-explorer/gcc-10.2.0/lib/gcc/x86_64-linux-gnu/10.2.0/../../../../x86_64-linux-gnu/bin/ld:
/tmp/example-35000b.o:(.debug_info+0x1be): undefined reference to `_ZZ3foovE4CSTR'

Where one realizes that somehow the template parameter of foo was stripped.

Notes:

  • Gcc (7.3 and 10.2) successfully compiles this example.
  • There is no reference to _ZZ3foovE4CSTR in the assembly -- nor to the other 2 variants, truth to be told -- which is probably why enabling optimizations "solve" the problem.

Is the above program conforming to the C++17 standard?

(And therefore am I observing an issue with the Clang compiler?)

Bonus question: and is there a work-around, to side-step the issue?

0 Answers
Related