Тут же решил воплотить давнее желание — собрать указатели на все локальные строки в глобальный map, но уже на первом шаге получил ошибку: "error: use of deleted function".
Зато понял, что имена переменных могут включать в себя угловые скобки (бессмысленная возможность):
#include <iostream>
template<class T>
int len = 2;
template<class Fn>
const char* s_str = Fn();
//template<class Fn>
//auto x = Fn();int main()
{
class centimeter {};
class meter {};
class nothing {};
len<centimeter> = 100 * len<meter>;
std::cout << len<nothing> << ',' << len<centimeter> << std::endl;
const char* str = "asdf";
auto oGetStr = [str]()->const char* {return str;};
//const char* p = s_str<decltype(oGetStr)>; // errorauto o2and2 = []()->int{return 2 + 2;};
//int n = x<decltype(o2and2)>; // errorreturn 0;
}
Может уже появился какой способ собрать указатели на локальные строки в глобальных переменных ? (Например, шаблон параметризованный локальной строкой...)
Здравствуйте, B0FEE664, Вы писали:
BFE>Может уже появился какой способ собрать указатели на локальные строки в глобальных переменных ? (Например, шаблон параметризованный локальной строкой...)
Поясни что нужно конкретно. Например передавать compile-time строки в шаблоны можно с некоторыми ухищрениями. А вот что ты понимаешь под "собрать"?
Здравствуйте, B0FEE664, Вы писали:
BFE>Заглянул в С++14, нашёл шаблонные переменные.
BFE>Тут же решил воплотить давнее желание — собрать указатели на все локальные строки в глобальный map
Что? Зачем?
BFE> но уже на первом шаге получил ошибку: "error: use of deleted function".
BFE>template<class Fn> BFE>const char* s_str = Fn();
BFE> auto oGetStr = [str]()->const char* {return str;}; BFE> //const char* p = s_str<decltype(oGetStr)>; // error
decltype(oGetStr) выозвратит тип ламбды
в выражении справа будет вызваться конструктор? экземпляра этой ламбды
const char* s_str = Fn();
BFE>Может уже появился какой способ собрать указатели на локальные строки в глобальных переменных ? (Например, шаблон параметризованный локальной строкой...)
BFE>Зато понял, что имена переменных могут включать в себя угловые скобки (бессмысленная возможность):
Как это?
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>Может уже появился какой способ собрать указатели на локальные строки в глобальных переменных ? (Например, шаблон параметризованный локальной строкой...) EP>Поясни что нужно конкретно. Например передавать compile-time строки в шаблоны можно с некоторыми ухищрениями. А вот что ты понимаешь под "собрать"?
Допусти, что все строки в программе обрамлены макросом:
Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык.
Здравствуйте, VTT, Вы писали:
BFE>>Зато понял, что имена переменных могут включать в себя угловые скобки (бессмысленная возможность): VTT>Как это?
В примере же есть:
len<centimeter> = 100 * len<meter>;
len<centimeter>
и
len<meter>
— это две разные переменные типа int.
Здравствуйте, B0FEE664, Вы писали:
BFE>Допусти, что все строки в программе обрамлены макросом: BFE>Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык.
Но ведь уже 20 лет gettext работает именно таким образом.
Здравствуйте, watchmaker, Вы писали:
BFE>>Допусти, что все строки в программе обрамлены макросом: BFE>>Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык.
W>Но ведь уже 20 лет gettext работает именно таким образом.
Неужели? Я думал, что для использования gettext'а нужны сторонние утилиты.
Здравствуйте, B0FEE664, Вы писали:
BFE>В примере же есть: BFE>
BFE>len<centimeter> = 100 * len<meter>;
BFE>
BFE>len<centimeter> BFE>и BFE>len<meter> BFE>- это две разные переменные типа int.
Тогда по вашей логике имена переменных могут включать пробелы, переносы строк, комментарии, макросы и прочее.
Можно же и так записать:
len< /* пишем пишем*/
centimeter
> = 0;
Просто это не переменные а две специализации шаблона переменной, состоящие из имени шаблона и списков параметров шаблона, заключенных в угловые скобки.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
BFE>Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык.
А что мешает определить TT как вызов функции, внутри которой живет глобальная переменная и дальше по тексту? Или нужна подстановка без поиска в словаре?
BFE>>Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык. W>А что мешает определить TT как вызов функции, внутри которой живет глобальная переменная и дальше по тексту? Или нужна подстановка без поиска в словаре?
А откуда в этой функции известно, что строка "asdf" вообще существует?
Здравствуйте, VTT, Вы писали:
VTT>Тогда по вашей логике имена переменных могут включать пробелы, переносы строк, комментарии, макросы и прочее.
Кстати, да!
VTT>Можно же и так записать: VTT>
VTT>Просто это не переменные а две специализации шаблона переменной, состоящие из имени шаблона и списков параметров шаблона, заключенных в угловые скобки.
В том-то и дело, что тип таких переменных не зависит от их специализации. Просто у этих переменных имена сложные, составные.
Здравствуйте, B0FEE664, Вы писали: BFE>А откуда в этой функции известно, что строка "asdf" вообще существует?
В смысле, что это строковой литерал, а не результат вызова (std::string("fu") + std::string("ck")).c_str()?
Здравствуйте, B0FEE664, Вы писали: VTT>>Просто это не переменные а две специализации шаблона переменной, состоящие из имени шаблона и списков параметров шаблона, заключенных в угловые скобки. BFE>В том-то и дело, что тип таких переменных не зависит от их специализации. Просто у этих переменных имена сложные, составные.
Ну, вроде бы шаблоны переменных вводили для типизированных констант и разных трейтов? Фактически, синтаксический сахар над:
Здравствуйте, Went, Вы писали:
VTT>>>Просто это не переменные а две специализации шаблона переменной, состоящие из имени шаблона и списков параметров шаблона, заключенных в угловые скобки. BFE>>В том-то и дело, что тип таких переменных не зависит от их специализации. Просто у этих переменных имена сложные, составные. W>Ну, вроде бы шаблоны переменных вводили для типизированных констант и разных трейтов? Фактически, синтаксический сахар над:
Это, да, но результат чудной.
W>Не? Есть еще какие-то принципиально новые применения?
А вот, только что придумал:
#include <iostream>
template<class T>
T x = T{};
void f()
{
class Test{ public: Test(){std::cout << "Test\n";} };
Test t = x<Test>;
}
int main()
{
std::cout << "start\n";
return 0;
}
Какой, думаете, будет вывод такой программы?
Похоже, что можно, таки, заставить выполнятся локальный код в глобальном пространстве. Возможно, что так было всегда, просто синтаксического сахара для мозгов не хватало...
BFE>Можно ли сделать так, чтобы была создана глобальная переменная содержащая список всех таких строк. Это может быть полезно при переводе сообщений на другой язык.
Если трюк описанный выше соответствует стандарту, то получается что-то типа:
#include <iostream>
#include <vector>
using namespace std;
vector<const char *> strings;
template<class T>
T run_it = T{};
#define GETTEXT(x) \
[] \
{ \
struct Action { Action() { strings.push_back(x); } };\
(void)run_it<Action>; \
return x; \
}() \
/**/void not_used()
{
const char *x = GETTEXT("first");
auto y = GETTEXT("second");
}
int main()
{
for(auto x : strings)
cout << x << endl;
}
Здравствуйте, Evgeny.Panasyuk, Вы писали:
BFE>>Какой, думаете, будет вывод такой программы? EP>Clang на Coliru выдал segfault.
Возможно это связано с инициализацией std::cout.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Если трюк описанный выше соответствует стандарту, то получается что-то типа:
Объясните мне, пожалуйста, в какой момент выполняется код добавления строки в хранилище.
При инициализации глобальной переменной run_it<Action>? А код в неиспользуемой функции как бы говорит, что такая глобальная перемення существует?
Забавно, из локального блока объявить глобальную переменную.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
EP>>Если трюк описанный выше соответствует стандарту, то получается что-то типа: TB>Объясните мне, пожалуйста, в какой момент выполняется код добавления строки в хранилище. TB>При инициализации глобальной переменной run_it<Action>?
да. TB> А код в неиспользуемой функции как бы говорит, что такая глобальная перемення существует?
да, можно и так сказать.
TB>Забавно, из локального блока объявить глобальную переменную.
Забавно не это, а то, что можно выполнить кусочек локального кода из вне.
Здравствуйте, T4r4sB, Вы писали:
EP>>Да, здорово, вот только на Clang что-то не заводится. TB>Судя по выхлопу, strings очищается перед вызовом мейна?!
Видимо не очищается, а просто конструируется позже run_it, хотя по идее должен раньше (можно попробовать сделать тест с порядком вызова конструкторов).
С синглтоном Майерса работает и на Clang.
EP>Видимо не очищается, а просто конструируется позже run_it, хотя по идее должен раньше (можно попробовать сделать тест с порядком вызова конструкторов).
Здравствуйте, B0FEE664, Вы писали:
BFE>А вот, только что придумал:
BFE>template<class T> BFE>T x = T{};
BFE> Test t = x<Test>;
Кто разъяснит, как это работает? Ведь до инициализации Test исполнение кода не доходит, почему же T<> инициализируется?
Какая связь между инстанцированием шаблона (T, StrMap) в локальном коде и инициализацией глобальной переменной?
Здравствуйте, flаt, Вы писали:
BFE>>А вот, только что придумал: BFE>>template<class T> BFE>>T x = T{};
BFE>> Test t = x<Test>;
F>Кто разъяснит, как это работает? Ведь до инициализации Test исполнение кода не доходит, почему же T<> инициализируется? F>Какая связь между инстанцированием шаблона (T, StrMap) в локальном коде и инициализацией глобальной переменной?
x — это глобальная переменная, следовательно она должна быть инициализирована в глобальном пространстве. То, что определение класса лежит где-то ещё не столь важно.
Дело тут даже не столько в том, что введены шаблонные переменные, а в том, что теперь в качестве параметра шаблона можно указать локальный класс. В сообщении trick, выше, это видно.
С этим кодом, кстати, возможна проблема из-за порядка инициализации глобальных переменных. Для надёжности, x следует сделать константой: const T x = T{};
F>Куда ткнуться почитать?
Не знаю, я стандарт просматривал...
Здравствуйте, B0FEE664, Вы писали: BFE>Может уже появился какой способ собрать указатели на локальные строки в глобальных переменных ? (Например, шаблон параметризованный локальной строкой...)
Это и в С++11 можно было сделать.
Вот ты там писал, что это можно использовать для перевода приложения.
Понравилась твоя идея, вот мой концепт реализации (работает в GCC и СLang c С++11).
В принципе даже контейнеры не понадобились.
Вспомогательная кухня, применил тут кое-какие свои давние идеи по реализации настоящих ct-строк:
SETUP_TR могут находиться в любом файле. Допустим, можно завести russian_tr.cpp и там написать перевод для нужных строк.
В продвинутой реализации можно было бы уйти от голых указателей и сделать свой класс "переводной" строки.
Тест "одним файлом" в онлайн компиляторе: http://rextester.com/WYUMS67445
Может быть будет полезно.
Да, именно.
Насчет constexpr функции с auto — то это работает только в С++14.
А приемы эти я изобретал еще на C++0x.
Можно применить вот такой вариант для С++11, если все еще есть сомнения насчет легитимности.
struct X
{
typedef decltype("abc") type;
static constexpr type chars() { return"abc"; }
};
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Его можно без проблем заменить на const char *, auto там исключительно для удобства.
Точно не вспомню пример, но иногда это не работало.
Возможно это были временные баги компиляторов, не помню уже.
Последний раз с этим всерьез возился кажется в 12 году.
Здравствуйте, B0FEE664, Вы писали:
BFE>В том-то и дело, что тип таких переменных не зависит от их специализации. Просто у этих переменных имена сложные, составные.
А в len<meter> можно явно/неявно присвоить len<centimeter> ?
Здравствуйте, rus blood, Вы писали:
BFE>>В том-то и дело, что тип таких переменных не зависит от их специализации. Просто у этих переменных имена сложные, составные. RB>А в len<meter> можно явно/неявно присвоить len<centimeter> ?
Да. Можно явно присвоить. len<meter> = len<centimeter>; присвоит значение len<centimeter> в len<meter>. Поэтому я и говорю, что это просто имена переменных.