1

C++20 introduces Class Types in Non-Type Template Parameters. As mentioned in the proposal, one of the motivations was the compile-time strings, and it enables to do this:

template < size_t size >
struct Literal : std::array<char,size>
{
  constexpr Literal(char const (&str)[size+1]) { for (size_t ii = 0; ii < size; ++ii) (*this)[ii] = str[ii]; }
};
template < size_t size > Literal(char const (&str)[size]) -> Literal<size-1>;
template < Literal literal > constexpr auto operator "" _lit() { return literal; }

template < Literal > struct Use { };
Use<"foo"_lit> use;

The proposal also says:

There have been multiple proposals[N3599][P0424R0] to relax the prohibition on string user-defined literals that take their raw form as individual char template arguments, and so far all of these proposals have failed to gain consensus.

The primary concern that gets raised in response to such proposals is that handling strings as packs of char template arguments is extremely costly in terms of the compiler’s CPU and memory usage, and allowing such UDLs would make very large packs of char values much more common than they are today. This may in turn result in pressure on compiler vendors to make their products perform well under such compile-time string processing workloads, which is difficult due to the strings being represented using a syntax and mechanism that was never intended to support such use cases.

Thus, though not mentioned directly, I assume this proposal was designed to avoid the extremely costly CPU and memory usage for the compilers while dealing with compile-time strings. Maybe this is to be possible because of the mangling approach and using Three-way comparison operator mentioned in the first section of the proposal. Is this assumption correct?

gcc-9.3 doesn't support the Three-way comparison operator but it supports Class Types in Non-Type Template Parameters. However, having compile-time strings in the above mentioned way with gcc-9.3 actually seems to result into extremely costly CPU and memory usage.

Is there any appropriate flag for gcc-9 or gcc-10 that will tune the compiler for such code?

Vahagn
  • 4,670
  • 9
  • 43
  • 72
  • Here we do not have compile time strings but an alias which can keep a string of a given length. The string itself is not part of the type, even if we can do something with constexpr. Compile time string are different types for every different string. In your example you only get different types for different *length* of your string which is totally different! – Klaus Jul 11 '20 at 15:25
  • @Klaus My understanding is that compile-time strings are *objects*, not *types*. Here `"foo"_lit` and `"bar"_lit` would be two different *objects* of the same *type* while `Use<"foo"_lit>` and `Use<"bar"_lit>` will be different *types*. Right? – Vahagn Jul 11 '20 at 15:50
  • 1
    Compile time strings are something like X<'H','a','l','l','o'> and are different types! But maybe I am wrong. In times of user defined types as template parms all is possible :-) And yes, your Use<>... are different types. – Klaus Jul 11 '20 at 16:31
  • @Klaus I just assume that it is `X<'H','a','l','l','o'>`-s who are causing *extremely costly CPU and memory usage* while the mentioned proposal provides an alternative that would not. However I am experiencing the same compilation performance for both solutions with `gcc-9.3`! And this is the question I am asking: was it supposed to be so? – Vahagn Jul 11 '20 at 19:38

0 Answers0