Open Aegel5 opened 3 years ago
Для этого в языке должна существовать возможность доступа к таблице идентификаторов. Насколько мне известно, такое предполагается пропозалом по рефлексии. Если не предполагается, то поправьте 😄
В С++ есть разные типы данных, и нет такого что все типы - классы унаследованные от общего предка и имеют метод преобразования в строку, на чем в общем и базируется трюки из $"Vars: a={a}, b={b}!" Python, Ruby, Groovy и т.д. В этих языках однозанчно можно сказать что у любого типа есть метод преобразующий его в строку. C++ язык другого уровня контроля абстракций, за счет чего на нем можно написать как ядро операционной системы так и прикладную CRUD программу. Поэтому типы можно создавать разные: структуры, массивы объединения, перечисления и т.д. И к строке они в общем могут приводится по усмотрению программиста, по умолчанию этого не происходит. Исходную проблему так же можно решить через библиотеки, например Boost Format
Речь идет исключительно о синтаксическом сахаре.
Если такое работает:
std::cout << std::format("Hello {}!\n", 123);
то значит должно работать и такое
std::cout << $"Hello {123}!\n";
std::format это шаблонная функция. Она использует синтаксис языка, а не втраиваетсья в него. А значит и не заставляет обязательно линковать стандартную библиотеку к любой программе или библиотеке. И не влияет на оптимизатор кода. В случае с синтаксисом - так уже не получится и выходит что на С++ уже нельзя писать embedded, ядра операционных систем, драйвера устройств и т.д. (да dynamic_cast, typed и static переменные - это явно промах который привел к разделению стандартной библиотеки на части, одна из которых это ABI). Посмотрите другие компилируемые языки, вы в них не найдете такой возможности, в отличие от интерпретаторов где такой синтаксис - стандарт.
А как насчет суффиксов для строк?
auto s = "abc"s;
Суффиксы - это новая возможность языка. При этом не мешают писать embedded, ядра операционных систем, драйвера устройств и т.д. Просто если нет определенных include, то программа не будет компилироваться.
Так и тут сделать: если определена функция std::format
- вызываем ее, если нет - ошибка.
@alexzh2, вы не правы.
Во-первых, это называется user-defined literals.
Во-вторых, это user-defined literals - это механизм языка С++: https://en.cppreference.com/w/cpp/language/user_literal
В-третьих, литералы для std::string
и других библиотечных типов являются частью стандартной библиотеки языка С++: https://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s. Они были даже добавлены в следующем стандарте после добавления user-defined literals как механизма языка.
Возьмём ваш пример:
int a = 10;
int b = 20;
auto res = $"Vars: a={a}, b={b}!";
Когда я захочу поменять тип a
с int
на Foo
, откуда компилятор узнает, как преобразовать экземпляр Foo
в строку? Нам потребуется решение проблемы. И эта проблема принципиально не имеет универсального решения на текущий момент
Проблема здесь даже не в классе Foo
, который мы не умеем преобразовывать — мы можем найти с десяток некрасивых решений. Есть другая, нерешаемая проблема — в самой строке. У нас есть std::string
, char const*
и, например, сторонние folly::fbstring
и QString
. Дело в том, что часто пользователи хотят в контексте каждого типа строки иметь различный алгоритм преобразования, учитывающий кодировку, ширину символа или даже выбирать другое текстовое представление в зависимости от дальнейшего использования этой строки. Проблема в том, что строковый литерал не знает, к какой из строк будет преобразован в будущем, а значит, не сможет выбирать способ форматирования, основываясь на целевом типе строки:
std::string x = $"Vars: a={a}, b={b}!";
folly::fbstring y = $"Vars: a={a}, b={b}!";
QString x = $"Vars: a={a}, b={b}!";
Можно придумать что-то с пользовательскими литералами, но всё это костыли на мой взгляд и будет ими оставаться, пока у нас не появятся достаточно мощные инструменты рефлексии, позволяющие создать библиотечную реализацию
Такой формат уже реализован в С#, пример:
И это невероятно удобный инструмент. Я не понимаю, почему другие языки не реализовывают подобный функционал.
Как конкретно реализовать это в С++ я не знаю, возможно тоже добавить
$
перед строкой: