Dies muss möglicherweise mit Abhängigkeitsinjektion kombiniert werden. In diesem Fall kann die Abhängigkeit ein Typ T mit einem Vorlagenparameter eingerichtet sein.
Code: Select all
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;
}
[*] Die Funktion do_logic hat eine Abhängigkeit von Recv . (Eine Funktion aus Sockets Library.) < /Li>
Code: Select all
do_logic
Hier ist eine Beispiel-Hauptfunktion für einen Unit-Test.
Code: Select all
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>
Bisher ist alles in Ordnung. Wir können eine Implementierung von do_logic
Code: Select all
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>
Das [url=viewtopic.php?t=15738]Problem[/url] hier ist ein Verstoß gegen Trocken. Während dies funktioniert, ist es nicht ideal, eine Synchronisation von zwei Codeblöcken über zwei verschiedene Dateien in einer Codebasis beizubehalten. Diese Dateien befinden sich wahrscheinlich an sehr unterschiedlichen Stellen im Quellbaum, da eine dieser Dateien für Unit -Tests bestimmt ist, während die andere für den Produktionscode bestimmt ist. (Nicht hier gezeigt, aber es würde wahrscheinlich STD :: Copy
Gibt es eine Lösung für dieses Problem, die nicht erforderlich ist, um auf Laufzeit -Dispatch zurückzugreifen? Dies ist eine Art Abhängigkeitsinjektion, bei der der Typ in die Funktion injiziert wird.
Code: Select all
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;
}
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>
Ich habe jedoch keine Ahnung, wie ich das implementieren soll. Ich bin mir vage bewusst, dass C ++ 20 (?) Konzepte eingeführt hat. Aus meiner ersten Lektüre in Konzepte war meine Interpretation jedoch, dass Konzepte eine abstraktere Idee sind, die die Typen zusammengibt. Ich bin mir nicht sicher, ob es das richtige Werkzeug für den Job ist? < /P>
Um ehrlich zu sein, kann es einen einfacheren Ansatz geben als die Idee, die ich hier vorgeschlagen habe. Es ist sehr wahrscheinlich, dass ich dies in die falsche Richtung nehme. Feedback dazu wäre sehr geschätzt. Vielen Dank im Voraus.