I know that this question is about C++17, but in C++20 I think that you can finally avoid using std::string&
arguments by using C++20's concepts.
You can write a concept that requires that the argument type is convertible to an std::string_view
and also convertible to either a const char*
or an std::string
, thus NULL-terminated. You can then convert the argument to a string_view
in the function body, and you can safely use that string_view
in C APIs, without doing runtime checks.
Here's an example from a small libcurl wrapper I maintain:
// NULL-terminated std::string_view
template<typename T>
concept Text = std::convertible_to<T, std::string_view> && (std::convertible_to<T, std::string> || std::convertible_to<T, const char*>);
void get(const std::string_view url, const Text auto... headers) noexcept {
// ...
struct curl_slist* curl_headers {nullptr};
if constexpr (sizeof...(headers) != 0) {
const std::array header_array {static_cast<std::string_view>(headers)...};
for (const std::string_view header : header_array) {
curl_headers = curl_slist_append(curl_headers, header.data());
}
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
// ...
}