I want to write a database wrapper that can operate different types of databases (e.g. sqlite, postgres, etc.), so the code that users are writing does not change regardless of what database they actually are using.
In my head, this calls for an abstract base class like:
class database {
public:
virtual bool query(const std::string &q) = 0;
// Other stuff
};
class sqlite : public database {
public:
bool query(const std::string &q) {
// Implementation
}
};
This looks good, but I am using variadic templates for escaping arguments inside queries (and I really like this idea, so I would want to hang on to it!), so unfortunately my base class rather looks like:
class database {
public:
template <typename... Args>
bool query(const std::string &q, const Args &... args) {
// Implementation
}
};
This stands in the way of creating an abstract class however, because templated functions cannot be virtual. The only thing I came up with so far is this construct
template <class DatabaseType>
class database {
public:
template <typename... Args>
bool query(const std::string &q, const Args &... args) {
return database_.query(q, args...);
}
private:
DatabaseType database_;
};
While this seems to work, with all the wrappers that do nothing but call the identically named database_
functions it does not look like a very good style to me. Is this the design pattern of choice here, or is there a cleaner, or more idiomatic way?
You can build a query object out of the arguments to the query
function, and pass it to a virtual query_impl
function.
[...] is there a cleaner, or more idiomatic way
You may want to look up CRTP to achieve polymorphic behavior with templates.
template <class concrete_db>
struct abstract_db {
template <typename... Args>
void query(std::string const& q, Args const&... args) {
static_cast<concrete_db *>(this)->query(q, args...);
}
};
struct postgres_db : abstract_db<postgres_db> {
template <typename... Args>
void query(std::string const& q, Args const&... args) {
// do something
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With