Целочисленная последовательность символов из пользовательского литерала, принимающая строки в качестве параметров

В настоящее время только двойники могут создавать шаблон символов в пользовательском литерале:

template <char...> double operator "" _x();
// Later
1.3_x; // OK
"1.3"_y; // C++14 does not allow a _y user-
         // defined operator to parse that as a template of chars

Есть ли умный способ создать std::integer_sequence символов, используя определенный пользователем литерал. Другими словами, каким должен быть код _y(const char*, std::size_t), чтобы я получил std::integer_sequence<char, '1', '.', '3'>?


person Vincent    schedule 30.01.2016    source источник
comment
N3599 может превратиться в C ++1Z.   -  person Columbo    schedule 30.01.2016
comment
Вам действительно нужен integer_sequence? Это пахнет XY-проблемой.   -  person Columbo    schedule 30.01.2016
comment
@Columbo Откуда у тебя эта информация? Последнее, что я слышал, было отклонено в EWG в пользу string_literal<N>.   -  person T.C.    schedule 30.01.2016
comment
@Т.С. Прямо от автора.   -  person Columbo    schedule 30.01.2016
comment
@Columbo Хм, когда это было?   -  person T.C.    schedule 30.01.2016
comment
Тем временем существует расширение GNU для template<typename CharT, CharT... Chars> stuff operator "" _x(); UDL, поддерживаемое gcc и clang.   -  person melak47    schedule 30.01.2016
comment
@Т.С. cplusplus.github.io/EWG/ewg-active.html#66 Механизм будет принят LEWG, и редакция документа (надеюсь) будет принята.   -  person Columbo    schedule 30.01.2016
comment
@Columbo IIRC сообщалось, что EWG выбрала N4121 (string_literal‹N›, см. EWG 139) вместо N4236 (который является расширением N3599 и использует пакет параметров). Не ясно, получим ли мы поддержку основного языка с пакетом, если они не хотят предоставлять возможности библиотеки.   -  person T.C.    schedule 30.01.2016
comment
@Т.С. Это правильно; то есть был выбран один из них, который (если я правильно помню почту Смита, которую я не могу проверить в банкомате) является всем, что требуется EWG (имеет ли это смысл?). В любом случае, есть (все еще) мотивация, нет сдерживающих факторов, реализации, которые ее поддерживают, и практически нет необходимости в каких-либо изменениях в формулировках, я уверен, что пересмотренная статья будет принята.   -  person Columbo    schedule 30.01.2016
comment
@Columbo, посмотрим. Я не уверен, что они добавят средство, которое создает пакеты параметров после отклонения чего-то, что на самом деле использует указанные пакеты. Конечно, я могу быть приятно удивлен...   -  person T.C.    schedule 30.01.2016
comment
@Т.С. Они отказались от пакетного решения, потому что другое лучше. Это не означает, что шаблоны строковых литералов бесполезны или что их не одобряют. Код, который я связал, требует этого, и он полезен (надеюсь: D). Да, посмотрим.   -  person Columbo    schedule 30.01.2016
comment
Если вы не хотите использовать расширения компилятора, самое близкое, что я знаю, используется так: constexpr const char literal[] = "delta"; using X = make_char_sequence<sizeof(literal), literal>;. Дайте мне знать, если вас интересуют подробности.   -  person Rumburak    schedule 01.02.2016
comment
Меня на самом деле интересуют подробности.   -  person Vincent    schedule 01.02.2016
comment
Вы должны иметь возможность расширить пакет символов в инициализатор массива: const char literal[]{Chars...}; Вы даже можете добавить нуль в конце: char literal[]{Chars..., '\0'};   -  person emsr    schedule 03.02.2016
comment
@Vincent Ну, строковые литералы не могут быть аргументами шаблона, отличными от типа, но могут быть константами области имен. Это показано в [temp.arg.nontype]/3. .   -  person Columbo    schedule 22.03.2016


Ответы (1)


На данный момент лучшее, что мы можем (переносимо) сделать, — это трюк с макросами, как показано для vtmpl::string. По сути, мы создаем список доступов, таких как

"abcd" -> {(0 < sizeof "abcd"? "abcd"[0] : 0), (1 < sizeof "abcd"? "abcd"[1] : 0), ...}

…которые мы обрезаем для получения желаемого результата.

Первый шаг легко сделать через BOOST_PP_ENUM, хотя рекурсивные макросы тоже подойдут (определение взято здесь) :

#define VTMPL_SPLIT_1(s, x, m) m(s, x)
#define VTMPL_SPLIT_4(s, x, m)    VTMPL_SPLIT_1  (s, x, m), VTMPL_SPLIT_1  (s, x+1  , m), VTMPL_SPLIT_1  (s, x+2  , m), VTMPL_SPLIT_1  (s, x+3  , m)
#define VTMPL_SPLIT_16(s, x, m)   VTMPL_SPLIT_4  (s, x, m), VTMPL_SPLIT_4  (s, x+4  , m), VTMPL_SPLIT_4  (s, x+8  , m), VTMPL_SPLIT_4  (s, x+12 , m)
#define VTMPL_SPLIT_64(s, x, m)   VTMPL_SPLIT_16 (s, x, m), VTMPL_SPLIT_16 (s, x+16 , m), VTMPL_SPLIT_16 (s, x+32 , m), VTMPL_SPLIT_16 (s, x+48 , m)
#define VTMPL_SPLIT_256(s, x, m)  VTMPL_SPLIT_64 (s, x, m), VTMPL_SPLIT_64 (s, x+64 , m), VTMPL_SPLIT_64 (s, x+128, m), VTMPL_SPLIT_64 (s, x+194, m)
#define VTMPL_SPLIT_1024(s, x, m) VTMPL_SPLIT_256(s, x, m), VTMPL_SPLIT_256(s, x+256, m), VTMPL_SPLIT_256(s, x+512, m), VTMPL_SPLIT_256(s, x+768, m)

Использование вышеуказанного выглядит так (включая обрезку):

#define VTMPL_STRING_IMPL(str, n) vtmpl::rtrim<vtmpl::value_list<decltype(*str), VTMPL_SPLIT_##n(str, 0, VTMPL_ARRAY_SPLIT)>>::type
#
#define VTMPL_STRING(str) VTMPL_STRING_IMPL(str, 64  )

Где rtrim определено в algorithms.hxx.

person Columbo    schedule 22.03.2016