c-具有已选择具有非const ref的复制构造函数的参数类型的函数?

前段时间,当我想编写is_callable< F,Args ...>时,我对某些代码的以下行为感到困惑.特征.重载解析不会调用非const ref接受参数的函数,对吗?为什么在下面它不拒绝,因为构造函数想要一个Test&amp ;?我希望它取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(Test).无法从您提供的rvalue复制测试,但是重载解析已经成功…从不检查是否已转换为int.

选择g(Eater)的原因是类型不完全匹配,不使用身份转换,并且编译器必须找到一个有效的转换例程. g(Slurper)不会,因为您无法从提供的参数中选择一个.

“为什么这不会失败:struct A {运算符int();}; void f(A&); void f(int); void g(){f(A());}”

因为f(A&)对于提供的参数而言不是可行的重载.在这种情况下,该参数是一个引用,并且温度不绑定到非常量这一事实可以影响分辨率.在这种情况下,该函数将变为该函数的那个​​版本,而该函数的那个​​版本将变为非候选函数,并且仅保留该函数的那个​​版本并起作用.

上一篇:c – 为什么std :: move采用前向引用?


下一篇:【GAMES101-现代计算机图形学课程笔记】Lecture 07 Shading 1 (Illumination, Shading and Graphics Pipeline)