gpt4 book ai didi

c++ - 重载分辨率 : is adjusting for const/ref not better than a user-defined conversion?

转载 作者:行者123 更新时间:2023-11-30 05:06:27 24 4
gpt4 key购买 nike

以下代码被 MSVC 2017 拒绝(但被 GCC/Clang 接受):

class BA 
{
private:
operator int() const;
};

template <typename A, typename B>
class Builder {};

template <typename C>
struct Concatenable;

template <int N> struct Concatenable<char[N]>
{
using type = char[N];
};

template <int N> struct Concatenable<const char [N]>
{
using type = const char[N];
};

template <> struct Concatenable<BA>
{
using type = char *;
};

template<typename A, typename B>
Builder<typename Concatenable<A>::type, typename Concatenable<B>::type>
operator+(const A &, const B &)
{
return {};
}

int main()
{
BA ba;
char array[] = {'a', 'b'};
ba + array;
}

错误:

example.cpp
40 : <source>(40): error C2666: 'operator +': 2 overloads have similar conversions
31 : <source>(31): note: could be 'Builder<char *,char [2]> operator +<BA,char[2]>(const A &,const B (&))'
with
[
A=BA,
B=char [2]
]
40 : <source>(40): note: or 'built-in C++ operator+(__int64, char [2])'
40 : <source>(40): note: while trying to match the argument list '(BA, char [2])'
40 : <source>(40): note: note: qualification adjustment (const/volatile) may be causing the ambiguity

看起来 MSVC 正在考虑将 char[2] 调整为 const char (&)[2] 并不比 BA 更好int 转换。根据我对标准的阅读,这不应该是真的。

[over.ics.rank] 表示标准转换序列总是比用户定义的转换序列更好的转换;现在:

  • 从模板实例化的operator+使用了两个标准的转换序列
  • 内置的(over ptrdiff_t, char *)一个用户定义的转换序列和一个标准的转换序列

因此,根据[over.match.best]中的规则,我的operator+总是不比另一个差,而且对于某些论点来说更好,所以应该优先考虑。

注意把BA中的operator int去掉,或者类似的把数组改成const char[],或者把第二个参数改成operator+ 使用非常量 B& 让 MSVC 开心。

我没看到什么?

最佳答案

隐式转换序列在每个参数的基础上进行比较。您不会将一个论点的 ICS 与另一个论点的 ICS 进行比较。当您试图确定哪个重载具有更好的第二个参数网络的 ICS 时,第一个参数的 ICS 是无关紧要的。

如果 X 在任何参数上不比 Y 差并且至少在一个参数上更好(忽略各种后期决胜局),则重载 X 优于重载 Y。如果一个重载对于一个论点具有更好的 ICS,但对于另一个论点具有更差的 ICS,那么两者都不比另一个好。

正如在 Slack 聊天中讨论的那样,这里的问题是 MSVC 错误地应用了 ICS-comparison tiebreaker这应该只适用于比较两个引用绑定(bind)。这使得内置函数在第二个参数上具有更好的 ICS。这是一个打破平局的标准转换序列并不重要;它仍然更好。

更多例子:

void f(int, ...);     // #1
void f(double, char); // #2
f(10, 'c'); // ambiguous: #1 is better for the first argument
// #2 is better for the second argument

struct C { operator int() const; };
void g(C, int); // #1
void g(int, double); // #2
g(C(), 1.0); // ambiguous: #1 is better for the first argument
// #2 is better for the second argument

关于c++ - 重载分辨率 : is adjusting for const/ref not better than a user-defined conversion?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47902452/

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