Есть желание получить на этапе компиляции список чисел, с возможностью добавления элементов с проверкой на существование — т.е. если есть уже значение, то компиляция ломается.
Пока в голову ничего не идет Реально ли такое сделать на 11ом стандарте? Подскажите, в какую сторону копать..
А вообще, может есть и какое-то другое решение для проблемы. Есть фиксированные ресурсы различных типов, они в разных частях софтины используются. Каждый ресурс может быть использован один раз, но из за ошибок могут быть попытки множественного использования, которые надо пресекать. Сейчас это проверяется в рантайме, что мне не очень нравится
Здравствуйте, Marty, Вы писали:
M>Пока в голову ничего не идет Реально ли такое сделать на 11ом стандарте? Подскажите, в какую сторону копать..
Реально. Система C++ темплейтов — тьюринг-полная.
Ну, например, создай какой-нибудь пустой темплейтный тип, параметризованный целым числом, и добавляй для каждого конкретного числа специализацию. Два раза для одного и того же числа компилятор тебе этого сделать не даст.
M>А вообще, может есть и какое-то другое решение для проблемы. Есть фиксированные ресурсы различных типов, они в разных частях софтины используются. Каждый ресурс может быть использован один раз, но из за ошибок могут быть попытки множественного использования, которые надо пресекать. Сейчас это проверяется в рантайме, что мне не очень нравится
Если это проверяется в процессе иницаилизации программы, это не так уж и плохо. Главное, просто и понятно, и взрывается сразу на старте. Хуже, если проверка устроена так, что взорваться может в любой момент.
Re[2]: Список целых на этапе компиляции с проверкой
Pzz>Ну, например, создай какой-нибудь пустой темплейтный тип, параметризованный целым числом, и добавляй для каждого конкретного числа специализацию. Два раза для одного и того же числа компилятор тебе этого сделать не даст.
Хм. Макросом?
Pzz>Если это проверяется в процессе иницаилизации программы, это не так уж и плохо. Главное, просто и понятно, и взрывается сразу на старте. Хуже, если проверка устроена так, что взорваться может в любой момент.
В принципе, ты наверно прав. Да и в компайл тайм не получится — использование-то может быть из разных единиц трансляции
Здравствуйте, Marty, Вы писали:
M> Да и в компайл тайм не получится — использование-то может быть из разных единиц трансляции
Так потом есть ещё ведь этап сборки.
Общее направление: пусть "использование" инстанциирует экземпляр примерно такой переменной: template <int n> int once = -1;, где значение параметра шаблона (это, кстати, не обязательно int) зависит от типа ресурса (или прямо им и является).
Тогда, хотя все единицы трансляции и скомпилируются успешно, линкер не сможет собрать программу, если в ней будут совпадения.
Re[4]: Список целых на этапе компиляции с проверкой
W>Так потом есть ещё ведь этап сборки.
W>Общее направление: пусть "использование" инстанциирует экземпляр примерно такой переменной: template <int n> int once = -1;, где значение параметра шаблона (это, кстати, не обязательно int) зависит от типа ресурса (или прямо им и является).
W>Тогда, хотя все единицы трансляции и скомпилируются успешно, линкер не сможет собрать программу, если в ней будут совпадения.
Здравствуйте, Marty, Вы писали:
M>А вообще, может есть и какое-то другое решение для проблемы. Есть фиксированные ресурсы различных типов, они в разных частях софтины используются. Каждый ресурс может быть использован один раз, но из за ошибок могут быть попытки множественного использования, которые надо пресекать. Сейчас это проверяется в рантайме, что мне не очень нравится
Ну, можно завести единый список идентификаторов ресурсов.
Это или один большой .h-файл с уникальными номерами (банально, энум без явных значений; или генерировать .h скриптом; или валидировать его скриптом же);
или набор .h-файлов и один диспетчерский файл с заведомо непересекающимися диапазонами
Заодно, все ресурсы окажутся перед глазами, — не надо будет грепать все исходники в поисках объявлений.
При этом у тебя не будет никаких ограничений вида "определение ресурса должно лежать строго внутри единицы трансляции, а наружу — только по ссылке на объявление",
как это было бы при использовании специализаций шаблонов, которые предложил watchmaker. (Да ещё надо побороться, чтобы компилятор и линкер умели диагностировать нарушение ODR, а не тупо посокращали якобы-инлайны).
P.S.
Какой смысл ты вкладываешь в слова "каждый ресурс может быть использован один раз"?
— определён в одной точке исходников
— прочитан в одной точке исходников и больше нигде
— прочитан единожды за запуск программы
— иное?
Ну и заодно, какого рода эти ресурсы?
Перекуём баги на фичи!
Re[5]: Список целых на этапе компиляции с проверкой
Здравствуйте, Marty, Вы писали:
W>>Общее направление: пусть "использование" инстанциирует экземпляр примерно такой переменной: template <int n> int once = -1;, где значение параметра шаблона (это, кстати, не обязательно int) зависит от типа ресурса (или прямо им и является). W>>Тогда, хотя все единицы трансляции и скомпилируются успешно, линкер не сможет собрать программу, если в ней будут совпадения.
M>Спасибо, идея годная
Сразу обрати внимание на ограничение: такие специализации можно сделать либо в том же, либо в обрамляющем пространстве имен (с явной спецификацией пространства имен). Если окажется, что "использование" происходит в каком-нибудь вложенном или несвязанном пространстве имен, то это может серьезно осложнить задачу. И в области видимости классов специализации делать не разрешается по стандарту, хоть некоторые компиляторы (msvc, например) и поддерживают эту возможность.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Сразу обрати внимание на ограничение: такие специализации можно сделать либо в том же, либо в обрамляющем пространстве имен (с явной спецификацией пространства имен). Если окажется, что "использование" происходит в каком-нибудь вложенном или несвязанном пространстве имен, то это может серьезно осложнить задачу. И в области видимости классов специализации делать не разрешается по стандарту, хоть некоторые компиляторы (msvc, например) и поддерживают эту возможность.
Зачем делать явную специализацию? Это какое-то ненужное переусложнение.
Достаточно в месте "использования" потрогать переменную любым способом (который ODR-used).
Ну то есть написать в once.h
#pragma once
template <typename T> int instance_me_only_once = 0;
А потом в люом месте включать этот заголовочный файл и трогать переменную:
W>Зачем делать явную специализацию? Это какое-то ненужное переусложнение. W>Достаточно в месте "использования" потрогать переменную любым способом (который ODR-used). W>Ну то есть написать в once.h
#pragma once
W>template <typename T> int instance_me_only_once = 0;
W>
W>А потом в люом месте включать этот заголовочный файл и трогать переменную:
W>Теперь если в другой единице трансляции тоже сделать ++instance_me_only_once<Foo>, то программа не соберётся.
Чего-то я не догоняю. Как может переменная, значение которой изменяется в runtime иметь какое-нибудь влияние на компиляцию? Что должно помешать этой переменной быть использованной повторно и какая ошибка при этом ожидается?
Вот я пробую промоделировать ситуацию на msvc-14.0. В существующий консольный проект добавляю такой вот заголовок once.h и помещаю обращение к instance_me_only_once<int> в две функции, определенные в разных единицах трансляции:
К>P.S. К>Какой смысл ты вкладываешь в слова "каждый ресурс может быть использован один раз"? К>- определён в одной точке исходников К>- прочитан в одной точке исходников и больше нигде К>- прочитан единожды за запуск программы К>- иное? К>Ну и заодно, какого рода эти ресурсы?
Изначально, это STMка, на борту пяток UARTов, для них есть пять глобальных соответствующих объектов, при необходимости UART передается в task (FreeRTOSный), который настраивает/включает этот UART и дальше с ним и работает. Сейчас у UART'а есть mutex, который захватывается на этапе инициализации, и если занят, то приехали. Мьютекс там конечно легкий по размеру, а потом в работе не используется, но все равно некрасиво. Без FreeRTOS тоже используется, несколько по другому, и так как своих мьютексов нет, там другая корявая проверка. Мне всё это не очень нравится.
Пока эту проблему обдумывал, пришли еще идеи, и подумалось, что неплохо было бы иметь универсальное решение — несколько областей, в которых нужно проверять уникальность использования — указателей, числовых идентификаторов и тп.
В принципе, глобальный контейнер для каждого из доменов меня устроит для стартовых проверок, просто изначально мечталось что можно на этапе компиляции всё отловить и указать, где конфликт используемых ресурсов
UPD Есть еще идея добавить немного COMа
Без управления созданием и временем жизни, просто функциональность QueryInterface. UIDы как-то жирновато для этого использовать, целые числа выглядят приятнее. В этом случае можно вести реестр этих UIDов в одном месте, но интереснее обдумать идею, когда каждый создает UIDы на свой вкус