dar*_*une 4 c++ explicit c++17
explicit可以用于例如。一个构造函数或转换函数,以避免隐式调用该构造函数/转换 - 简而言之。
我想知道是否有可能以某种方式显式地明确单个参数(缺少滚动新类型)?也许使用编译器扩展?
使用引用使复制构造变得不可能,因此这是一种解决方案,尽管不是我正在寻找的解决方案。有时能够explicit在功能级别强制执行将是简洁的工具/界面说明符。
void f(std::string& s); //cannot copy convert into s
void f(const std::string& t);//calling with char* allowed
Run Code Online (Sandbox Code Playgroud)
特别是对于字符串,应该使用什么类型来避免从char*?
您不能显式标记参数,但您可以做的是添加一个具有右值引用参数的重载并将其删除,例如
void f(const std::string& t);
void f(std::string&&) = delete;
Run Code Online (Sandbox Code Playgroud)
这将允许f接受 a std::string,但如果由于隐式转换而创建了右值,则将选择右值引用重载,并且您将收到有关使用已删除函数的编译器错误。
这样做的原因是右值引用参数在重载解析中优于对 const 的引用,因此在传递临时值时将始终调用它。只有在选择函数后,编译器才会看到它被删除,因此它会发出错误。
使用 C++20,您可以执行以下操作:
void f(std::same_as<std::string> auto const& s);
Run Code Online (Sandbox Code Playgroud)
使用 C++17,这相当于:
template <typename T,
std::enable_if_t<std::is_same_v<T, std::string>, int> = 0>
void f(T const& s);
Run Code Online (Sandbox Code Playgroud)
也就是说,我们必须T准确地推断出std::string(哪些字符串文字或其他char指针显然不是)。
请注意,这会拒绝以下类型:
struct D : std::string { };
Run Code Online (Sandbox Code Playgroud)
这也不需要转换。如果您想允许这些,那就是将概念更改为std::derived_from或enable_if使用std::is_convertible_v<T*, std::string*>.