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

时间:2017-02-06 00:41:37

标签: c++ optional c++-standard-library boost-optional

我有一个签名为:

的函数
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"));

编译器会发现需要std::optional并进行转换。但是,这太冗长了。感谢C ++ 11,我也可以这样做:

func({"Hello"});

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

2 个答案:

答案 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
}

另请参阅thisthis以供参考。

答案 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