17

我有一个函数,其签名是:

void func(std::optional<std::string> os = std::nullopt);

(在正式可用std::experimental::optional之前,我一直在使用别名。)std::optional

但是,我很难干净地调用它。编译器将拒绝执行两次隐式转换(const char*std::stringstd::optional<std::string>)以使用原始 C 字符串文字调用它。我可以这样做:

func(std::string("Hello"));

编译器会认为 astd::optional是必需的,并进行转换。但是,这太冗长了。感谢 C++11,我也可以这样做:

func({"Hello"});

虽然这样更好,但仍然不理想。我希望能够像其他任何需要std::string. 这可能吗?让函数采用另一种参数类型是可以的,只要它的行为类似于/可以直接转换为std::optional. 谢谢。

4

2 回答 2

16

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
}

另请查看thisthis以供参考。

于 2017-02-06T01:06:10.267 回答
8

您可以使用一些模板和 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
于 2017-02-06T01:14:36.807 回答