Статический полиморфизм 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!?

Можно ли прийти к этому?

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>{ /*...*/ };
Другие вопросы по тегам