Статический полиморфизм CRTP: можно ли заменить базовый класс макетом?

Я использую статический полиморфизм CRTP на сервере веб-сокетов, чтобы отделить сетевой код от бизнес-логики. Базовый класс вызывает методы производного класса для обработки сообщений, производный, в свою очередь, вызывает базовый класс для отправки/получения. Это работает как шарм, выглядит примерно так:

template<typename Derived>
class WebsocketSessionBase {
    // basic websocket send/receive stuff

    void someBaseMethod() {
        static_cast<Derived*>(this)->otherDerivedMethod();
    }
};

class WebsocketSession : public WebsocketSessionBase<WebsocketSession> {
    // specific business logic

    void someDerivedMethod() {
        otherBaseMethod();
    }
};

Теперь идет модульное тестирование. Поскольку код развязан, я бы хотел, чтобы тестовая функциональность в классах была отдельно.

Тестировать базовый класс просто:

class TestSession : public WebsocketSessionBase<TestSession> {
    // same interface as WebsocketSession, but test code, cool!
};

Но как протестировать производный класс? Мне пришло в голову добавить параметр шаблона Base, что делает тестовый код в порядке (Base — это фиктивный класс). Но в итоге у меня есть 2 класса шаблонов, ссылающихся друг на друга в производственной версии... :(

template<typename Base>
class TestableWebsocketSession : public Base {
};

using TestedWebsocketSession = TestableWebsocketSession<MockBase>;
using ProdWebSocketSession = TestableWebsocketSession<WebsocketSessionBase<... // infinite loop - now what!?

Можно ли пройти через это?


person Gyorgy Szekely    schedule 08.01.2018    source источник


Ответы (1)


Я не знаю, стоит ли это того, но вы можете сделать WebsocketSession шаблоном класса, принимающим параметр шаблона шаблона:

template<class T>
struct WebsocketSessionBase { /*...*/ };

template<template<class> class B>
struct WebsocketSessionDerived: B<WebsocketSessionDerived<B>>{ /*...*/ };

using WebsocketSession = WebsocketSessionDerived<WebsocketSessionBase>;

using DerivedTestSession = WebsocketSessionDerived<WebsocketSessionMockBase>;
struct BaseTestSession : WebsocketSessionBase<BaseTestSession>{ /*...*/ };
person Massimiliano Janes    schedule 08.01.2018