Вызов функций с помощью std:: необязательных параметров

У меня есть функция, чья подпись:

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 ответа

Решение

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
}

Также взгляните на это и это для справки.

Вы можете сделать это с небольшим количеством шаблонов и 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
Другие вопросы по тегам