3

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

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()! Я попробовал это с clang ++ - 3.9 и msvC++ - 19.00, та же жалоба, которая действительно меня скептически.

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

Я должен ожидать разделителя цифр ' в моем шаблоне пользовательских литералов, тоже, теперь?

Update 1: в случае ' нормально:

Можно использовать цифры-SEP как ПОШ все рода вещи, скажем, комплексных числа. Было бы хорошо определено поведение `52.84'67.12_i 'для 52.84 + 67.12i?'

Udpdate 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, поэтому на него можно положиться.

+1

Рассмотрите, как '01' и' 1' означают то же самое, что интерпретируются как 'int', но вы можете хотеть, чтобы' 01_bin' и '1_bin' интерпретировались по-разному (битовая строка длиной 2 по сравнению с битовой строкой длина 1). Независимо от того, что говорит стандарт (об этом уже сказано), имеет смысл, что вы получаете точное написание, которое пользователь использовал. Это зависит от вас, чтобы решить, какие отличия имеют значение, а какие нет. – hvd

ответ

4

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

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

N4140 § 2.13.8 [lex.ext]/3

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

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

где п - последовательность символов источника c c ... c k.[Примечание: Последовательность с с ... с к может содержать только символы из основного набора символов источника. - примечание к концу]

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

0

Насколько я читал here, разделитель разрешен только в том случае, если вы получаете литерал как число, а не когда оператор является сырым литералом. Это означает, что вы избавитесь от разделителя компилятором, если тип параметра оператора равен unsigned long long, а не если он является одним из необработанных, которые получают C-строку или char.

+0

Такой вид был бы потрясающим! Можно использовать digit-sep как sep для всех видов, скажем, сложных чисел. Было бы хорошо определено поведение '52.84'67.12_i 'для * 52.84 + 67.12i *? – towi

+1

Глядя на [this] (http://stackoverflow.com/a/40265094/4299382) ответ в связанном вопросе кажется, что это согласуется с описанным там поведением chrono, где оператор raw literal получает разделитель как есть приготовленный (получение 'ull') игнорирует его. К сожалению, я не могу найти достаточно ясную ссылку в стандартном тексте. –

+1

Если '' использует его, @ howard-hinnant часто наблюдает за этим сайтом. Возможно, Он это увидит. – towi