Сделать аргумент явным? - PullRequest
4 голосов
/ 04 марта 2020

explicit можно использовать, например. конструктор или функция преобразования, чтобы избежать неявного вызова этого конструктора / преобразования - короче.

Меня интересует, можно ли каким-то образом сделать единственный аргумент (если не использовать новый тип) ) возможно, используя расширения компилятора?

Использование ссылки делает невозможным копирование, поэтому это решение, хотя и не то, которое я ищу. Иногда было бы полезно иметь точный спецификатор инструмента / интерфейса, чтобы можно было форсировать explicit на уровне функций.

void f(std::string& s); //cannot copy convert into s

void f(const std::string& t);//calling with char* allowed

В частности, для строк, какой тип следует использовать, чтобы избежать построения из char*?

Ответы [ 2 ]

9 голосов
/ 04 марта 2020

Вы не можете пометить параметр как явный, но то, что вы можете сделать, это добавить перегрузку, имеющую ссылочный параметр rvalue, и удалить его как

void f(const std::string& t);
void f(std::string&&) = delete;

То, что это будет делать, это разрешит f принять std::string, но если из-за неявного преобразования создано значение rvalue, вместо этого будет выбрана перегрузка ссылки rvalue, и вы получите ошибку компилятора об использовании удаленной функции.

Причина это работает в том, что ссылочный параметр rvalue превосходит ссылку const в разрешении перегрузки, поэтому он всегда будет вызываться при передаче временного. Только после выбора функции компилятор видит, что он удален, и выдает ошибку.

7 голосов
/ 04 марта 2020

С C ++ 20 вы можете сделать:

void f(std::same_as<std::string> auto const& s);

С C ++ 17 это эквивалентно:

template <typename T,
    std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
void f(T const& s);

То есть мы должны вывести T должно быть точно std::string (какие строковые литералы или другие char указатели явно не являются).

Обратите внимание, что это отклоняет такие типы, как:

struct D : std::string { };

, которые также не требуют преобразования. Если вы хотите разрешить это, это меняет концепцию на std::derived_from или enable_if для использования std::is_convertible_v<T*, std::string*>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...