Статическая (contexpr) функция отправка и инъекция зависимости в шаблонах в C ++ 23C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Статическая (contexpr) функция отправка и инъекция зависимости в шаблонах в C ++ 23

Сообщение Anonymous »

Я пишу несколько модульных тестов для проекта C ++. Более того, я пытаюсь написать тест для функции, которая зависит от recv . Другими словами, функция, которую я хочу написать тест для вызовов recv .
Типичный способ написать тест с такой зависимостью, как это было бы найти решение для отправки времени выполнения. Существует как минимум два простых подхода. Одной из этих реализаций является «реальная» реализация. Это завершает recv . Другой - это «фальшивая» реализация. Вызовы виртуальной функции и динамическая диспетчерская в среде выполнения. Предоставьте решение здесь.
[*] Используйте std :: variant (или аналогично). В этом случае простой оператор IF может использоваться для переключения между реальными и макетными вызовами функций во время выполнения. Возможно, можно будет использовать contexpr или какое -то другое решение о компиляции, чтобы переключаться между вызовом двух реализаций функции. В этом случае зависимостью может быть тип t , введенный с использованием параметра шаблона.

Код: Выделить всё

ssize_t do_logic(
const int sock_fd,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {

// imagine there is some code block here
{
// code block A
}

ssize_t recv_size = recv(sock_fd, p_buffer.get(), buffer_size, 0);

// imaging there is some code block here
{
// code block B
}

return recv_size;
}

int main() {

int sock_fd = socket(AF_INET, SOCK_STREAM, 0);

// this is all just MWE noise
sockaddr_in server_address;
std::memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(1234);
bind(sock_fd, reinterpret_cast(&server_address), sizeof(server_address));
listen(sock_fd, 10);

const size_t buffer_size = 1024;
const auto p_buffer = std::make_unique(buffer_size);

do_logic(sock_fd, p_buffer, buffer_size);

return 0;
}
Вещи, чтобы отметить:
  • Функция do_logic зависит от Recv . (Функция из библиотеки сокетов.) < /Li>

    Код: Выделить всё

    do_logic
    также имеет дополнительный код, который я пытаюсь избежать повторения. (Сухо) Они представлены кодовыми блоками Block A и Block B .
Вот пример Main функция для единичного теста.

Код: Выделить всё

int main() {

std::string sock_data = "Hello World. This is some example data for unit testing."

const size_t buffer_size = 1024;
const auto p_buffer = std::make_unique(buffer_size);

do_logic(sock_data, p_buffer, buffer_size);

return 0;
}
< /code>
Пока все хорошо. Мы можем написать реализацию do_logic 
, которая использует перегрузку функций. (Время компиляции.) Однако именно здесь дела идут не так.

Код: Выделить всё

ssize_t do_logic(
std::string sock_data,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {

// imagine there is some code block here
{
// code block A
}

ssize_t recv_size = recv(sock_data, p_buffer.get(), buffer_size);

// imaging there is some code block here
{
// code block B
}

return recv_size;
}
< /code>
Проблема здесь является нарушением сухой. Хотя это будет работать, не идеально поддерживать синхронизацию двух кодовых блоков в двух разных файлах в кодовой базе. Эти файлы, вероятно, находятся в очень разных местах в дереве источника, поскольку один из этих файлов предназначен для модульного тестирования, в то время как другой предназначен для производственного кода.  (Не показано здесь, но это, вероятно, назвал бы std :: copy 
, или что -то в этом роде.)
Есть ли решение этой проблемы, которая не требует прибегания к отправке времени выполнения? Это своего рода инъекция зависимости, когда тип вводится в функцию.

Код: Выделить всё

template
ssize_t do_logic(
T sock,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {

// imagine there is some code block here
{
// code block A
}

constexpr if ( /* ? */ ) {
// this `recv`: the `recv` from the sockets library
ssize_t recv_size = recv(sock, p_buffer.get(), buffer_size, 0);
}
else {
// this `recv`: an implementation of a function `recv(std::string, ...etc...)`
// which we write. It could be a null implementation, or it could call
// `std::copy`.
//
// ssize_t recv(std::string, const auto& p_buffer, const auto buffer_size) { return 0; }
//
ssize_t recv_size = recv(sock, p_buffer.get(), buffer_size);
}

// imaging there is some code block here
{
// code block B
}

return recv_size;
}
Для строки contexpr if (/ *? */) , что я хочу сделать, это что -то вроде
constexpr if ( T isa typename int ) { }
else if ( T isa typename std::string ) { }
else {
static_assert("T must be either type int or type std::string");
}
< /code>
Однако я понятия не имею, как это реализовать. Я смутно осознаю, что C ++ 20 (?) Представил концепции. Однако из моего первоначального чтения в понятиях моя интерпретация заключалась в том, что концепции - это более абстрактная идея, которую группы связывают типы вместе. Я не уверен, является ли это правильным инструментом для работы? Вполне вероятно, что я принимаю это в неправильном направлении. Отзывы об этом будут очень оценены. Заранее спасибо.

Подробнее здесь: https://stackoverflow.com/questions/794 ... mplates-in
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»