Я просто использую этот синтаксис для параметров, где это необходимо:
пример объявления конструктора:
t_array(const t_ownership_policy::t_take& policy, THESpecialType* const arg);
Используется на месте вызова:
t_array array(t_ownership_policy::Take, THESpecialTypeCreate(...));
Где t_ownership_policy::t_take
- это просто имя типа двусмысленной перегрузки с перегрузкой.
В этой системе существует несколько политик, каждая из которых имеет отдельные типы. Я предпочел уникальные типы для каждой политики, потому что типизированное перечисление (например) не поддерживает инициализацию так же легко, и слишком легко передать неподдерживаемую политику функции или конструктору. «Полиморфные» политики могут уменьшить количество символов, но это неприятно, потому что подталкивает обнаружение ошибок к времени выполнения.
Для «возвращения»:
void func(t_container<t_type>& outValue);
Где t_container
- какой бы тип контейнера указателя вы не выбрали. Тогда тип контейнера уже реализует необходимый шаблон. Этот контейнер может быть чем-то вроде shared_ptr
, или какой-то специализацией, которую вы написали.
и для более сложных типов, я часто буду использовать синтаксис так:
void func(t_special_container& outValue) {
...
outValue.take(ptr);
- or -
outValue.copy(ptr);