Подтвердить что ты не робот

Оператор С++ 11 "с двойным параметром

Рассмотрим:

struct str {};

str operator"" _X(long double d) {
    return str();
}

Это компилируется с помощью g++ 4.7.2 Стена std = С++ 11

но теперь, если я даю двойной:

str operator"" _X(double d) {
    return str();
}

Появляется следующее сообщение об ошибке: main.cpp | 3 | error: 'str operator "_X (double)" имеет недопустимый список аргументов

В чем проблема? Связано ли это с "Невозможно переопределить значение встроенного суффикса литерала" (FAQ по Stroustrup)? Можете ли вы придумать обходное решение?

4b9b3361

Ответ 1

В чем проблема?

Проблема в том, что стандарт запрещает это. За абзац 13.5.8./3 стандарта С++ 11 по пользовательским литералам:

Объявление оператора буквальности должно иметь параметр-объявление-предложение, эквивалентный одному из следующее:

const char*
unsigned long long int
long double
char
wchar_t
char16_t
char32_t
const char*, std::size_t
const wchar_t*, std::size_t
const char16_t*, std::size_t
const char32_t*, std::size_t

Что касается обходного пути, я не уверен, что это необходимо, так как следующее работает отлично (a double получает неявное преобразование в long double, поэтому вы можете передать литералы типа double):

struct str {};

str operator"" _X(long double d) {
    return str();
}

int main()
{
    str s = 4.0_X;
}

Ответ 2

Я думаю, что это предотвратит неоднозначные перегрузки. Что делать, если вам разрешено определять следующий набор перегрузки

str operator"" _X(long double ld);
str operator"" _X(double d);
str operator"" _X(float f);

Можете ли вы привести примеры пользовательских литералов в исходном коде, которые будут сопоставляться с каждым из вышеперечисленных? Нет, нет возможности ограничить литерал конкретным типом данных с плавающей запятой.

Что может быть полезно в этом наборе:

str operator"" l_X(long double ld);
str operator""  _X(long double d);
str operator"" f_X(long double f);

С тех пор вы можете написать

3.0_X  // treated like a double
3.0l_X // treated like a long double
3.0f_X // treated like a float