一段时间以前 is_callable<F, Args...> 特征。过载分辨率不会调用函数接受非const Ref的参数,对吗?为什么不拒绝以下内容,因为构造函数想要一个 Test&?我希望它能 f(int)!

struct Test {
  Test() { }

  // I want Test not be copyable from rvalues!
  Test(Test&) { }

  // But it's convertible to int
  operator int() { return 0; }
};

void f(int) { }
void f(Test) { }

struct WorksFine { };
struct Slurper { Slurper(WorksFine&) { } };
struct Eater { Eater(WorksFine) { } };

void g(Slurper) { }
void g(Eater) { } // chooses this, as expected

int main() {
  // Error, why?
  f(Test());

  // But this works, why?
  g(WorksFine());
}

错误消息是

m.cpp: In function 'int main()':
m.cpp:33:11: error: no matching function for call to 'Test::Test(Test)'
m.cpp:5:3: note: candidates are: Test::Test(Test&)
m.cpp:2:3: note:                 Test::Test()
m.cpp:33:11: error:   initializing argument 1 of 'void f(Test)'

您能解释一下为什么一个工作,但另一个不起作用?

有帮助吗?

解决方案

过载分辨率选择最接近所提供参数的函数。您提供了测试。无需转换 - 使用的身份转换。因此,功能分辨率选择F(测试)。无法从您提供的RVALUE复制测试,但是超负荷分辨率已经成功了...从未检查转换为INT。

g(Eater) 之所以选择,是因为类型不完全匹配,因此不使用身份转换,并且编译器必须找到有效的转换例程。 g(Slurper) 不是因为您不能从提供的论点中赚取一个。

“为什么这个人没有失败: struct A { operator int(); }; void f(A&); void f(int); void g() { f(A()); }"

因为F(A&)不是提供参数的可行过载。在这种情况下,参数是参考,而温度不结合到非const的事实可以实现分辨率。在这种情况下,它确实如此,并且该函数的版本变成了非候选,仅留下一个并且它起作用。

其他提示

基本上,对于超载分辨率,假定A类型的对象可以转换为类型A的对象,无论两者上的任何一个CV验证如何。

从N1905草案出发:

13.3.3.1:Overloading.Overload分辨率。best可行函数。插入转换序列

6 当参数类型不是参考时, ,隐式转换序列从参数表达式对参数的拷贝性化模型。隐式转换序列是将参数表达式转换为参数类型的RVALUE所需的序列。 [[ 笔记: :当参数具有类类型时,这是为第13条而定义的概念转换;实际初始化是根据构造函数定义的,不是转换。 - 结尾注 ] 顶级CV资格化的任何差异都取决于初始化本身,并且不构成转换。 [ 例子: :A类型A的参数可以从类型ConstA的参数初始化。该情况的隐式转换序列是身份序列。它不包含从consta到A的“转换”。 结束示例 ] 当参数具有类类型并且参数表达式具有相同的类型时,隐式转换序列是身份转换. [...]

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top