我有一个签名为:
的函数void func(std::optional<std::string> os = std::nullopt);
(我正在使std::experimental::optional
别名,直到std::optional
正式可用。)
然而,我很难干净地称呼它。编译器将拒绝执行两次隐式转换(const char*
➝std::string
➝std::optional<std::string>
)以使用原始C字符串文字进行调用。我可以这样做:
func(std::string("Hello"));
编译器会发现需要std::optional
并进行转换。但是,这太冗长了。感谢C ++ 11,我也可以这样做:
func({"Hello"});
虽然方式更好,但它仍然不理想。我希望能够像使用std::string
的任何其他函数一样调用此函数。 这可能吗?让函数采用另一种参数类型是可以的,只要它的行为类似于/可以直接转换为std::optional
。感谢。
答案 0 :(得分:10)
C ++ 14将一堆用户定义的文字添加到标准库中,以使代码更简洁。它看起来像这样:
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
}
答案 1 :(得分:6)
你可以用一些模板和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)));
}
如果字符串可以使用转发T
进行构造,但仅当std::optional<std::string>
不可构造时才会选择此重载。
您的函数可以使用任何可以构造字符串的对象调用:
func("potato"); // working, forward the string literal to a std::string