Как пользовательские литералы играют вместе с разделителем цифр?

Я просто модифицировал старый пример моего кода, добавив разделитель цифр в пользовательский литерал, анализируемый с помощью шаблона с переменными параметрами:

namespace lits {
// helper for 1 arg
template<char C> int bin();  // common
template<>       int bin<'1'>() { return 1; } // spec.
template<>       int bin<'0'>() { return 0; } // spec.
// helper 2 or more args
template<char C, char D, char... ES>
int bin() {
return bin<C>() << (sizeof...(ES)+1) | bin<D,ES...>() ;
}
// operator"" _bin
template<char...CS> int operator"" _bin()
{ return bin<CS...>(); };
}
int main() {
using namespace lits;
int number = 1000'0000_bin; // <<< I added a ' here
}

Мальчик, я был удивлен, когда г ++ 6.2.0 пытался создать экземпляр bin<'\''>, Он пытался передать ' как char на мой шаблон template<char...CS> int operator"" _bin()! Я попробовал это с лязг ++ — 3,9 а также MSVC ++ — 19,00, та же самая жалоба, которая действительно заставляет меня скептически относиться.

У меня такое чувство, что это может быть неправильное поведение. Я бы понял это, если бы мой литерал был в кавычках, скажем, "1000'0000"_bin, но эта форма не существует для шаблона оператора «», верно?

Должен ли я ожидать разделитель цифр ' в моём шаблоне пользовательские литералы тоже сейчас?

Обновление 1: в случае, если ' все в порядке:

Можно использовать цифру-sep как sep для всех видов вещей, скажем, комплексных чисел. Будет ли поведение `52.84’67.12_i ‘для 52,84 + 67.12i быть хорошо определенным?

Обновление 2: В качестве реакции некоторые из комментариев. Следующие компиляции:

#include <iostream>
#include <string>
using std::string;

namespace lits {
// helper
template<char C> string sx() { return string{}+C; }
// helper 2 or more args
template<char C, char D, char... ES>
string sx() {
return sx<C>() + sx<D,ES...>();
}
// operator"" _sx
template<char...CS> string operator"" _sx()
{ return sx<CS...>(); };
}
int main() {
using namespace lits;
std::cout << 10000000_sx << '\n';
std::cout << 10'000'000_sx << '\n';
std::cout << 0x00af_sx << '\n';
std::cout << 0x0'c'0'a'f_sx << '\n';
std::cout << 007_sx << '\n';
std::cout << 0b01_sx << '\n';
// the following do not work:
//std::cout << 0b0a8sh3s1_sx << '\n';
//std::cout << "abcde"_sx << '\n';
}

И вывод:

10000000
10'000'000
0x00af
0x0'c'0'a'f
007
0b01

Что означает, что шаблон получает все символы: префиксы и разделители цифр — все они. (G ++ — 6.2.0)

Как подсказывает ответ @ krzaq, похоже, что это план Std, поэтому на него можно положиться.

3

Решение

Насколько я могу сказать, да. Как объяснил Вот, Цифровые разделители являются законными членами целочисленных литералов, определенных пользователем.

И целочисленный литерал шаблона определяется как:

N4140 § 2.13.8 [lex.ext] / 3

Иначе (S содержит шаблон буквального оператора), L лечится
как вызов формы

operator "" X <’c1’, ’c2’, ... ’ck’>()

где N является исходной символьной последовательностью c1с2…сК. [ Замечания: Последовательность
с1с2…сК может содержать только символы
из основного исходного набора символов. —конечная нота ]

Там нет ни слова об удалении разделителей.

4

Другие решения

Столько, сколько я прочитал Вот разделитель допускается только тогда, когда вы получаете литерал в виде числа, а не когда оператор является необработанным литералом. Это означает, что компилятор избавит вас от разделителя, если тип параметра оператора unsigned long long, не если это один из тех, кто получает C-строку или символ.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector