Reputation: 1489
I have a function whose signature is:
void func(std::optional<std::string> os = std::nullopt);
(I’m aliasing std::experimental::optional
until std::optional
is officially available.)
However, I’m having difficulty calling it cleanly. The compiler will refuse to perform two implicit conversions (const char*
➝ std::string
➝ std::optional<std::string>
) to call it with a raw C-string literal. I can do this:
func(std::string("Hello"));
And the compiler will figure that a std::optional
is needed, and do the conversion. However, this is way too verbose. Thanks to C++11, I can also do this:
func({"Hello"});
While this is way better, it's still not ideal. I'd like to be able to call this function like any other that takes a std::string
. Is this possible? Making the function take another parameter type is okay, as long as it behaves similarly to/is directly convertible to std::optional
. Thanks.
Upvotes: 17
Views: 10359
Reputation: 41760
You can do that with a bit of templates and sfinae:
template<typename T, std::enable_if_t<
std::is_constructible<std::string, T>::value &&
!std::is_constructible<std::optional<std::string>, T>::value>* = nullptr>
void func(T&& s) {
void func(std::string(std::forward<T>(s)));
}
This overload will be picked when a string would be constructible with a forwarded T
but only when std::optional<std::string>
is not constructible.
You function will be callable with any object that a string can be constructed with:
func("potato"); // working, forward the string literal to a std::string
Upvotes: 8
Reputation: 10415
C++14 adds a bunch of user-defined literals to the standard library in order to make code less verbose. It looks something like this:
using namespace std::string_literals; // needed
// using namespace std::literals; // also ok, but unnecessary
// using namespace std::literals::string_literals; // also ok, but why??
int main()
{
std::string str = "string"s;
^^^^^^^^
// This is a std::string literal,
// so std::string's copy constructor is called in this case
}
Also take a look at this and this for reference.
Upvotes: 16