gpt4 book ai didi

c++ - 避免在人为模糊的重载函数调用中拼写出类型

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:40:17 26 4
gpt4 key购买 nike

最小示例程序:

#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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com