Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> работа с template в C++11 
:(
    Опции темы
Ivan.
Дата 10.8.2012, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Здравствуйте.
Я думаю уже многие оценили преимущества нового компилятора C++11, но для беспокойного программиста все таки остаются вопросы как реализовать ту или иную задачу.
У меня вопрос по template-ам. С появлением новых возможностей у меня снова появилось поле для размышления. Уже давно я пытаюсь создать строку с определенными атрибутами и получить на ее указатель непосредственно в месте ее использования.
Пример: 
Код
printf("Количество: %d", Count);

Здесь при вызове функции printf компилятор подставляет указатель на заранее подготовленную строку в коде или оперативной памяти.
Размещение строк в оперативной или кодовой памяти зависит от нескольких факторов:
- атрибут const;
- толерантность кодовой и оперативной памяти;
- единое или раздельное пространство областей памяти.
В моем случаи это микроконтроллер архитектуры AVR8, для которого памяти не толерантны и существуют 2 способа работы с переменными, расположенными в оперативной или кодовой памяти: printf и printf_P. Соответственно и создание переменных производится с разными атрибутами. Например:
Код
const char Text1[] = "Abc"; //В оперативной памяти
const char PROGMEM Text2[] = "Abc"; //В кодовой памяти

Получается, что для вызова функции со строкой, расположенной в кодовой памяти ее нужно заранее создать. Пример:
Код
const char PROGMEM Text[] = "Abc";
int main(){
    puts_P(Text);
}
Как вы понимаете - это очень неудобно, заранее подготавливать сотни строк, присваивать им какие то имена, при удалении мест использования пред подготовленных строк приходится их потом подчищать и т.д.

Вернемся к новому C++11, чем же он поможет нам с этой проблемой:
Шаблоны с переменным числом аргументов
Код
template<char ...Text> struct _ProgMemStr{static const char PROGMEM v[sizeof ...(Text)];};
template<char ...Text> const char _ProgMemStr<Text...>::v[] = {Text...};

Немного напомни новый синтаксис:
template<char ...Text> - шаблон с переменным числом аргументов типа char с присвоенным именем Text;
sizeof ...(Text) - возвращает количество аргументов;
С остальным все как раньше.
Что мы получаем?
Код
puts_P(_ProgMemStr<"Abc">::v);

Правда проблема осталась в том, что и новый C++ так и не научился принимать в качестве аргумента шаблона строку и придется писать следующим образом:
Код
puts_P(_ProgMemStr('A', 'b', 'c', '\0'); //Не удобно

Придумал следующую реализацию:
Код
#define ProgMemStr(T) _ProgMemStr<T[0], T[1], T[2], T[3], T[4], ..., T[N]>::v

Но она не работоспособна, так как компилятор ругается на то, что я пытаюсь взять символ строки выходящий за пределы массива. (была строка "Abc", а я пытаюсь взять 4, 5, и т.д. символ.
Идем дальше, прибавим к исходной строке еще N байт:
Код

#define _T "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
#define ProgMemStr(T) _ProgMemStr<(T _T)[0], (T _T)[1], (T _T)[2], (T _T)[3], (T _T)[4], ..., (T _T)[N]>::v

Следующая проблема - каждая строка будет занимать N байт. Эту проблему можно решить с помощью специальных шаблонов:
Код

template<size_t S, char ...Text> struct _ProgMemStr;
template<char T1, char ...> struct _ProgMemStr<1, T1, ...>{static const char PROGMEM v[S];};
template<char T1, char ...> const char _ProgMemStr<1, T1, ...>::v[] = {T1};
template<char T1, char T2, char ...> struct _ProgMemStr<2, T1, T2, ...>{static const char PROGMEM v[S];};
template<char T1, char T2, char ...> const char _ProgMemStr<2, T1, T2, ...>::v[] = {T1, T2};
//И так далее
#define _T "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
#define ProgMemStr(T) _ProgMemStr<sizeof(T), (T _T)[0], (T _T)[1], (T _T)[2], (T _T)[3], (T _T)[4], ..., (T _T)[N]>::v

Конечно код получается очень грамосским, но это вариант работает. Мне не нужно заботится о количестве символов, главное, чтобы не превысить N; Автоматически отсеиваются повторные темплейты и можно вызывать в любой момент:
Код

struct TMyStruct {const char* Name; int Value;};
TMyStruct MyValue = {ProgMemStr("Abc"), 10};
int main()
{
    puts_P(MyValue.Name);
    puts_P(ProgMemStr("Abc"));
}

Я возрадовался, когда решил эту многолетнюю задачу, компилятор с ней справляется довольно быстро и это то, что я хотел. С помощью темплейтов я научился создавать массивы объектов и массивы указателей на объекты, созданные с помощью таких же темплейтах и располагающие данные в кодовой памяти. Но счастье мое было не долгим. Оказывается, что в компиляторе существует предел на количество символов входных данных в теплейт - это 64к развернутых данных. конечно после сборки такой переменной она будет занимать всего пару килобайт, но ее не удается собрать. а каждая моя строка занимает 256 байт (этим я ограничился) независимо от желаемой строки "Abc", сотня таких строк съест 24к символов прекомпилятора как минимум (имеется ввиду если они будут посланы в один какой то очень сложный темплейт).

Вопрос, какой еще можно придумать способ создания строки не упираясь в данные ограничения компилятора?


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
korian
Дата 11.8.2012, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



ндя, не понимаю, почему не придумали в компиляторе под avr что-то типа
P"My String", по типу как L"My string" для wchar_t

думаю надо порыть в сторону увеличения ограниченый компилятора, если у него есть такие параметры...
PM   Вверх
alexSl
Дата 11.8.2012, 01:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


проходил мимо



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 22.2.2008

Репутация: нет
Всего: нет



Цитата(Ivan. @  10.8.2012,  12:13 Найти цитируемый пост)
Вопрос, какой еще можно придумать способ создания строки не упираясь в данные ограничения компилятора?


Может быть умные указатели ?
PM MAIL   Вверх
borisbn
Дата 11.8.2012, 03:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



> В моем случаи это микроконтроллер архитектуры AVR8
> преимущества нового компилятора C++11
если не секрет, что за компилятор си++ 11 под микроконтроллер?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ivan.
Дата 11.8.2012, 06:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



avrgcc-4.7.0-avrlibc-1.8.0 поддерживает c++11 гугли. есть скомпиленный для винды


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
rodnover
Дата 11.8.2012, 08:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 7.4.2009

Репутация: нет
Всего: 10



http://habrahabr.ru/post/140357/

Это не то? Переопределение собственных литералов. Правда сам этим еще так и не пользовался. Только читал.
PM MAIL   Вверх
Ivan.
Дата 11.8.2012, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



литералы читал, строковые литералы выполняются в рантайме, а сырые литералы сводятся к темплейтам и возвращаемся к проблеме №1


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
korian
Дата 11.8.2012, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 651
Регистрация: 8.3.2008
Где: Украина, Харьков

Репутация: 3
Всего: 17



Все-таки, все уже "украдено" за нас smile

http://www.avrfreaks.net/index.php?name=PN...p;postorder=asc
Цитата

The pgmspace.h header also exposes a neat little macro, PSTR, which by some GCC magic allows you to create inline strings:

Code:
LCD_puts(PSTR("Program Memory String"));


This stops you from having to clutter your program up with hundreds of variables which hold one-time-used strings. The downside to using the PSTR macro rather than a PROGMEM modified string variable is that you can only use the PSTR string once. 


PM   Вверх
Ivan.
Дата 11.8.2012, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(alexSl @  11.8.2012,  01:37 Найти цитируемый пост)
Может быть умные указатели ?

у меня проблема не в использовании, а в объявлении. в том примере он сперва создает строку с различными атрибутами, а уже потом присваивает к "Умному" указателю


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0785 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.