Return std :: array from user defined literal in C ++ 11

I just installed gcc-4.8.1 and was very excited when I realized that I can do -std = C ++ 1y and get a multi-line constexpr. I am curious to know if there is a way to make this work?

#include <array> constexpr auto operator "" _a1 (const char* text, const size_t size) -> std::array<char,size> { std::array<char,size>() blah; std::strncpy(blah.data(), test, size); // do some stuff to blah at compile time return blah; } int main() { auto blah = "hello world"_a2; } 

But I get a lot of horror:

 $ g++ test.cpp -std=gnu++1y -Wall -Werror -Wextra -Weffc++ -pedantic test.cpp:3:100: error: use of parameter 'size' outside function body constexpr auto operator "" _a1 (const char* text, const size_t size) -> std::array<char,size> { ^ test.cpp:3:100: error: use of parameter 'size' outside function body test.cpp:3:100: error: use of parameter 'size' outside function body test.cpp:3:104: error: template argument 2 is invalid constexpr auto operator "" _a1 (const char* text, const size_t size) -> std::array<char,size> { ^ test.cpp: In function 'int main()': test.cpp:26:17: error: unable to find string literal operator 'operator"" _a1' auto blah = "hello world"_a1; 

Anyway, for this to happen? I cannot return std :: string from constexpr and it seems like I can not do anything with templates or decltype. Anyway, to get a constant expression from a parameter?

+4
source share
1 answer

You need a template literal operator. Functional parameters are never valid constant expressions; even if normal use makes sense, your statement still needs to support an explicit form call

 operator "" _a1 ( "hello", 5 ); 

For integer and floating user literals, there is a boilerplate form that can return an array :

 template< char ... c > constexpr std::array< char, sizeof ... (c) > operator "" _a1 () { return { c ... }; } 

This is not supported (yet?) For string literals, possibly due to problems with multibyte encoding.

So, you are out of luck in this particular approach.

However, you can take another label and take the string as an array.

 template< std::size_t size > constexpr std::array< char, size > string_to_array( char const (&str)[ size ] ) { return string_to_array( str, make_index_helper< size >() ); } template< std::size_t size, std::size_t ... index > constexpr std::array< char, size > string_to_array( char const (&str)[ size ], index_helper< index ... > ) { return {{ str[ index ] ... }}; } 

An index_helper support template is required to create an integer count package { 0, 1, 2, ... size } .

Also note that constexpr may not work for the application you have in mind. The constexpr function cannot contain a sequence of peremptory statements. The only statement that allows us to calculate something is the return constructor, or for constexpr , member initialization.

Update: Here is a small demonstration of what you can do in C ++ 11.

+7
source

Source: https://habr.com/ru/post/1490621/


All Articles