Entry tags:
Зодачка
Специально для любителей шОблоноф и прочих C++ наворотов. :) Сразу пердупердяю: задачка с подвохом.
Дано.
В программе есть некоторое количество классов, которые являются элементами односвязных списков с internal storage (проще говоря, это когда указатель на следующий элемент является членом класса).
Классы имеют вид:
Причем, варьируется не только название класса, но и название поля "nextListItem".
Задача.
Написать универсальную функцию вставки в начало списка с применением template, inline и pointer-to-member операторов. На входе должны быть: вставляемый элемент; указатель на первый элемент; название поля, указывающего на следующий элемент и тип класса. Функция может быть глобальной или членом namespace или функцией какого-либо нового класса - важно, чтобы она была одна, но работала для всех тех классов. Функция должна работать примерно так же, как ниже представленный #define:
Посчитать количество строк в полученной функции. Факультативно: перечислить и обосновать преимущества перед приведенным #define.
Дано.
В программе есть некоторое количество классов, которые являются элементами односвязных списков с internal storage (проще говоря, это когда указатель на следующий элемент является членом класса).
Классы имеют вид:
class MyClass... { MyClass *nextListItem;
Причем, варьируется не только название класса, но и название поля "nextListItem".
Задача.
Написать универсальную функцию вставки в начало списка с применением template, inline и pointer-to-member операторов. На входе должны быть: вставляемый элемент; указатель на первый элемент; название поля, указывающего на следующий элемент и тип класса. Функция может быть глобальной или членом namespace или функцией какого-либо нового класса - важно, чтобы она была одна, но работала для всех тех классов. Функция должна работать примерно так же, как ниже представленный #define:
#define INSERT_TO_LIST(firstItemPtr, item, nextItemName) \ (item)->nextItemName= (firstItemPtr), (firstItemPtr)= (item)
Посчитать количество строк в полученной функции. Факультативно: перечислить и обосновать преимущества перед приведенным #define.
мм?
Что я пропустил?
Re: мм?
Re: мм?
Re: мм?
По-твоему ее можно решить? (не говори пока решение, если ты его знаешь)
Re: мм?
Re: мм?
Re: мм?
Да, тело класса, конечно, придется курочить так или иначе. Лично для себя я сделал так:
В самом классе MyClass приходится использовать friend:
Ну и вызов так:
Позитив этого подхода -
1. Сакральное поле nextItem по-прежнему закрыто от некорректного использования.
2. В ListHelper можно написать еще кучу функций для работы со списком, и под каждую новую функцию уже не надо будет писать "friend" и модифицировать MyClass.
Re: мм?
Что-то не то.
> А если оставишь ее внешней, то получится, что ты обращаешься из функции класса к внешней функции unshift которая уже в свою очередь пытается обратиться к приватному полю member класса.
Внешняя функция unshift пытается обратиться не к приватному полю, а к некому (по указателю). Права на доступ к полю, чтоб создать указатель на него, нужны только создателю указателя (в данном случае пользователю unshift, item::prependList()).
По этой же причине твой код не работает: для вызывающего кода такого понятия, как MyClass::nextItem, не существует. Контроль доступа ведь производится на уровне имен (это не Ява какая-нибудь).
Так что я не могу придумать решения, требующее только подружить класс item с кем-нибудь. Указатель на next по-любому приходится создавать внутри item.
Re: мм?
Re: мм?
- тут надо struct вместо class
В данном случае main должна быть объявлена friend класса item. Так что приватность все-таки срабатывает, но не там, где я думал. У меня оно работает по стечению обстоятельств - то поля public, то вызов из самого класса item. :) Надо будет придумать что-нибудь по-лучше на тот случай, когда перестанет работать.
Re: мм?
Единственный разумный вариант, который потребует от item только дружбы — писать специализации функции а-ля:
Но это уже онанизм очень похожий на вариант юзера dii.
Re: мм?