“Концепти” на C + +

Всім доброго часу доби.

Придумано і написано під впливом деяких публікацій Страуструпа на тему концептів в C + +.
Захотілося мені одного разу незвичайного – зробити так, щоб нешаблонні функції / методи на C + + могли приймати в якості аргументу будь-який об’єкт, що має певний набір методів, приблизно так:

void fn(VectorWrapper<int> x)
{
for (size_t i = 0; i < x.size(); ++i)
{
doSomething(x[i]);
}
}
::std::vector<int> sv;
QList<int> qv;
OtherSuperVector<int> ov;
fn(sv);
fn(qv);
fn(ov);

Причому зробити це не використовуючи спадкування від базового класу.
Як це можна зробити, читайте під катом.
Основна складність, з якою я зіткнувся – створення типу VectorWrapper, який мав би тільки один шаблонний аргуент (тип збереженого значення), але при цьому міг бути створений з чого-завгодно, що має певний набір методів. У моєму прикладі це operator [] і size (). Після деякої кількості часу роздумів народилася приблизно така конструкція, яка використовує можливості стандарту C + +11.

template <typename T>
class VectorWrapper
{
public:
template <typename C>
VectorWrapper(C& container) :
_getter([&container](size_t i) -> T&
{
return container[i];
}),
_sizeGetter([&container]() -> size_t
{
return container.size();
})
{
}
T& operator[](size_t i)
{
return _getter(i);
}
size_t size()
{
return _sizeGetter();
}
private:
::std::function<T&(size_t) > _getter;
::std::function<size_t() > _sizeGetter;
};

У підсумку, при створенні об’єкта цього класу, лямбда захоплюється переданий в конструктор об’єкт, а методи самого класу просто викликають збережені лямбда, смикають, в свою чергу, методи захопленого об’єкта.
Тепер в цей врапперов можна загорнути все, що завгодно, що має методи size () і operator [].

Не знаю, чи можна це використовувати десь у реальному житті, свою проблему, яку я хотів вирішити таким способом, я вирішив раніше, ніж придумав все це неподобство. Так само є підозра, що якщо повсюдно використовувати подібні класи, можна сильно погіршити продуктивність.

Ну і чисто з цікавості питання хабражітелям – чи можна створити подібне, не вдаючись до допомоги лямбда і C + +11?

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*