使用std :: optional参数调用函数

Tha*_*esy 10 c++ optional c++-standard-library boost-optional

我有一个功能,其签名是:

void func(std::optional<std::string> os = std::nullopt);
Run Code Online (Sandbox Code Playgroud)

(我正在走样,std::experimental::optional直到std::optional官方可用.)

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

func(std::string("Hello"));
Run Code Online (Sandbox Code Playgroud)

并且编译器将确定需要a std::optional,并进行转换.但是,这太冗长了.感谢C++ 11,我也可以这样做:

func({"Hello"});
Run Code Online (Sandbox Code Playgroud)

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

Dei*_*Dei 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
}
Run Code Online (Sandbox Code Playgroud)

也看看这个这个供参考.


Gui*_*cot 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)));
}
Run Code Online (Sandbox Code Playgroud)

当字符串可以转发T时可以构造,但只有当std::optional<std::string>它不可构造时,才会选择此重载.

您可以使用任何可以构造字符串的对象来调用您的函数:

func("potato"); // working, forward the string literal to a std::string
Run Code Online (Sandbox Code Playgroud)