- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
最小示例程序:
#include <vector>
void f(std::vector<int>) {} // #1
void f(std::vector<void *>) {} // #2
int main() { f({ 1 }); }
从直觉上来说,这是一个有效的程序:使用重载 #1 的调用是有效的,使用重载 #2 的调用是错误的,因此应该选择重载 #1。这就是 clang 所做的。
不幸的是,按照标准,这似乎是模棱两可的,因为 std::vector<void *>
有一个构造函数可以用 int
调用, 通过将其隐式转换为 size_t
.该构造函数是 explicit
的事实应该在重载决议期间被忽略,如果选择该重载,程序将只是格式错误。 GCC 以不明确为由拒绝调用,看起来这样做是正确的。
我可以修改代码,让 GCC 通过拼写类型名称来接受调用:f(std::vector<int>{ 1 });
.我也可以使用带有默认参数的标记分派(dispatch),以允许显式指定要使用的重载,同时允许像以前一样接受现有调用。
这两个都是可以接受的,但在返回到实际代码时会很快变得相当冗长。是否有另一个选项可以让我避免拼出完整的类型名称,但坚持使用当前的重载?我想了想 { 1, }
可能有效,但当然无效,int i = { 1, };
也完全有效,不能用来避免#2。
如果它有助于排除一些替代方案,那么真正的代码确实涉及 std::vector<int>
和 std::vector<T>
并且确实涉及带有包含单个整数表达式的花括号初始化列表的调用,但是 T
是用户定义类型,不是内置类型,表达式不是常量值。
“否”是可以接受的答案,但在那种情况下,请详细说明,请表明没有这样的选择。
最佳答案
总是很难证明是否定的,但考虑到引入的可能性
using I=std::vector<int>;
我认为您真的是在问“有没有一种方法可以避免向 size_type
的标准转换,从而将其他重载从争用中移除”?
很明显,您不能对 int
本身做任何事情,甚至可以在隐式转换为 int
之后进行标准转换。但我们可以(当然)bring SFINAE to bear :
struct A {
int i;
template<class T,std::enable_if_t<std::is_same_v<T,int>>* =nullptr>
operator T() const {return i;}
};
然后你可以写
f({A{1}});
(用户定义的文字会更简洁,但您说的是非常量表达式。)
这是否意味着答案取决于您,但我很确定没有其他方法可以在不允许标准转换的情况下使用大括号初始化器。
关于c++ - 避免在人为模糊的重载函数调用中拼写出类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52469723/
我是一名优秀的程序员,十分优秀!