Какие новые возможности пользовательские литералы добавляют в C ++? - PullRequest
137 голосов
/ 26 октября 2008

C ++ 11 вводит пользовательских литералов , что позволит вводить новый литеральный синтаксис на основе существующих литералов (int, hex, string, float) чтобы любой тип мог иметь буквальное представление.

Примеры:

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

На первый взгляд это выглядит очень круто, но мне интересно, насколько это применимо на самом деле, когда я пытался придумать, что суффиксы _AD и _BC создают даты, я обнаружил, что это проблематично из-за порядка операторов. 1974/01/06_AD сначала оценил бы 1974/01 (как простые int с) и только позже 06_AD (не говоря уже о августе и сентябре, которые должны быть написаны без 0 по восьмеричным причинам). Это можно обойти, если использовать синтаксис 1974-1/6_AD, чтобы порядок вычисления операторов работал, но он был неуклюжим.

Итак, к чему сводится мой вопрос: считаете ли вы, что эта функция оправдает себя? Какие еще литералы вы хотели бы определить, чтобы сделать ваш код C ++ более читабельным?


Обновлен синтаксис для соответствия окончательному проекту в июне 2011 года

Ответы [ 12 ]

2 голосов
/ 26 октября 2008

C ++ обычно очень строго относится к используемому синтаксису - за исключением препроцессора, вы не можете использовать его для определения собственного синтаксиса / грамматики. Например. мы можем перегружать существующие операции, но мы не можем определять новые - IMO, это очень соответствует духу C ++.

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

Даже предполагаемое использование может усложнить чтение исходного кода: одна буква может иметь далеко идущие побочные эффекты, которые никоим образом не могут быть идентифицированы из контекста. При симметрии u, l и f большинство разработчиков выбирают отдельные буквы.

Это может также превратить область видимости в проблему, использование отдельных букв в глобальном пространстве имен, вероятно, будет считаться плохой практикой, а инструменты, которые предполагают более простое смешивание библиотек (пространства имен и описательные идентификаторы), вероятно, потеряют свою цель.

Я вижу некоторые достоинства в сочетании с "авто", также в сочетании с библиотекой юнитов, таких как бустовые единицы , но этого недостаточно, чтобы заслужить это признание.

Интересно, однако, какие умные идеи мы выдвигаем.

0 голосов
/ 26 октября 2008

Шум линии в этой штуке огромен. Также читать ужасно.

Дайте мне знать, они объясняли это новым синтаксическим добавлением какими-либо примерами? Например, есть ли у них пара программ, которые уже используют C ++ 0x?

Для меня эта часть:

auto val = 3.14_i

Не оправдывает эту часть:

std::complex<double> operator ""_i(long double d) // cooked form
{ 
    return std::complex(0, d);
}

Даже если бы вы использовали i-синтаксис в 1000 других строках. Если вы пишете, вы, вероятно, также напишите 10000 строк чего-то еще. Особенно, когда вы все еще, вероятно, будете писать в основном везде:

std::complex<double> val = 3.14i

'auto' - ключевое слово может быть оправдано, но только возможно. Но давайте возьмем только C ++, потому что в этом аспекте он лучше, чем C ++ 0x.

std::complex<double> val = std::complex(0, 3.14);

Это как ... так просто. Даже мысль, что все стандартные и заостренные скобки просто хромают, если вы используете их повсюду. Я не начинаю догадываться, какой синтаксис есть в C ++ 0x для превращения std :: complex в complex.

complex = std::complex<double>;

Возможно, это просто, но я не верю, что это так просто в C ++ 0x.

typedef std::complex<double> complex;

complex val = std::complex(0, 3.14);

Может быть? > :)

В любом случае, суть в том, чтобы написать 3.14i вместо std :: complex (0, 3.14); не экономит много времени в целом, за исключением нескольких супер особых случаев.

...