Оператор С++ 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)?
Можете ли вы придумать обходное решение?
Ответы
Ответ 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