User-defined string literal syntax can't use compile-time length

325 views
Skip to first unread message

orion.c...@gmail.com

unread,
Jul 31, 2015, 4:08:31 PM7/31/15
to ISO C++ Standard - Discussion
operator "" _suffix(const char* string, const std::size_t length)
The above syntax specified for user-defined string literals fails to address the case of producing complex objects at compile time based on the length of the string literal.

The following code cannot be compiled as length is a parameter. However, semantically, this code is often called in a context where the length is in fact known at compile time.
constexpr auto operator "" _test(const char* string, const std::size_t length) -> std::array<char, length> {
    std
::array<char, length> data{};
   
for (unsigned index(0); index < length; ++index) {
        data
[index] = string[index];
   
}
   
return data;
}

Yet, that functionality, producing complex objects at compile time from a string literal (and only a string literal), exists.
template<std::size_t length>
constexpr auto test(const char(&string)[length]) -> std::array<char, length> {
    std
::array<char, length> data{};
   
for (unsigned index(0); index < length; ++index) {
        data
[index] = string[index];
   
}
   
return data;
}

It seems to me to be an oversight that another (group) of user-defined string literal forms does not exist in the form
template <std::size_t length> operator "" _suffix(const char(&string)[length])
(And, potentially, and oversight that string literals were not given access to the variadic template form that user-defined integer and floating point literals have access to, and that integer and floating point literals also do not have access to this string literal syntax somehow, though that would be more difficult.)

This appears to me to be a defect in the ability to define user literals, making it impossible to define literals which produce std::array objects, or other objects with variable size determined entirely at compile time. (I used a toy example for simplicity, but I encountered this issue trying to create a literal for base64 data, and it seems it would also hinder other reasonable pursuits like creating a literal for a true compile-time string class.)

Have I missed anything?

Róbert Dávid

unread,
Aug 3, 2015, 1:35:20 PM8/3/15
to ISO C++ Standard - Discussion, orion.c...@gmail.com
Have I missed anything?

The following form should be valid:
template<char... X>
auto operator "" _test() -> std::array<char, sizeof...(X)> {
   
return { X... };
}
It is even less code than your example (I'd even say, significantly).

However, neither GCC and Clang seems to accept it.

The standard's (N4527, but as far as I can tell, this is there since a C++11) 13.5.8/8 has an example, what is practically equivalent to the one above:
template <char...> double operator "" _\u03C0(); // OK: UCN for lowercase pi
But that also does not compile with GCC/Clang: http://goo.gl/v2a94x
The funny thing is that Clang's compiler error *does* tell that it tried matching a template operator, but it just failed. GCC does not even say it tried the template version. I say this is an unimplemented C++11 feature for both.

MSDN suggests that this form of UDL operators are supported by MSVC 2015, but I don't have a VS 2015 at hand, and their webcompiler seems to be offline, so I cannot test.

Best, Robert

dyp

unread,
Aug 3, 2015, 1:55:45 PM8/3/15
to std-dis...@isocpp.org
On 03.08.2015 19:35, Róbert Dávid wrote:
>
>>
>> Have I missed anything?
>>
>
> The following form should be valid:
> template<char... X>
> auto operator "" _test() -> std::array<char, sizeof...(X)> {
> return { X... };
> }
> It is even less code than your example (I'd even say, significantly).
>
> However, neither GCC and Clang seems to accept it.

The template form is only valid for user-defined-integer-literals and
user-defined-floating-literals, see [lex.ext]p3-5

Róbert Dávid

unread,
Aug 3, 2015, 2:21:34 PM8/3/15
to ISO C++ Standard - Discussion, dyp...@gmx.net


2015. augusztus 3., hétfő 19:55:45 UTC+2 időpontban dyp a következőt írta:
On 03.08.2015 19:35, Róbert Dávid wrote:
>
>>
>> Have I missed anything?
>>
>
> The following form should be valid:
> template<char... X>
> auto operator "" _test() -> std::array<char, sizeof...(X)> {
>     return { X... };
> }
> It is even less code than your example (I'd even say, significantly).
>
> However, neither GCC and Clang seems to accept it.

The template form is only valid for user-defined-integer-literals and
user-defined-floating-literals, see [lex.ext]p3-5

Hm, that explains. Question is then, why is this not allowed?

Alternatively, there was a thread somewhere about constexpr function parameters. It didn't get anywhere, if the length parameter would be constexpr, it could be used to define the return type. This way, when the parameter is not a compile-time constant, it would be ill-defined, but UDL operators cannot be called in other contexts anyway.

Best,
Robert

Richard Smith

unread,
Aug 3, 2015, 3:04:36 PM8/3/15
to std-dis...@isocpp.org, dyp...@gmx.net
On Mon, Aug 3, 2015 at 11:21 AM, Róbert Dávid <lrd...@gmail.com> wrote:


2015. augusztus 3., hétfő 19:55:45 UTC+2 időpontban dyp a következőt írta:
On 03.08.2015 19:35, Róbert Dávid wrote:
>
>>
>> Have I missed anything?
>>
>
> The following form should be valid:
> template<char... X>
> auto operator "" _test() -> std::array<char, sizeof...(X)> {
>     return { X... };
> }
> It is even less code than your example (I'd even say, significantly).
>
> However, neither GCC and Clang seems to accept it.

The template form is only valid for user-defined-integer-literals and
user-defined-floating-literals, see [lex.ext]p3-5

Hm, that explains. Question is then, why is this not allowed?

See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3599.html (both Clang and GCC implement this as an extension).

EWG rejected this without prejudice, requesting that it have library support added and be re-proposed. I'm optimistic that such library support will be available very soon, in the form of one of these proposals:


Alternatively, there was a thread somewhere about constexpr function parameters. It didn't get anywhere, if the length parameter would be constexpr, it could be used to define the return type. This way, when the parameter is not a compile-time constant, it would be ill-defined, but UDL operators cannot be called in other contexts anyway.

Best,
Robert

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.

Reply all
Reply to author
Forward
0 new messages