显式对象参数是否允许可转换类型?

Des*_*old 3 c++ this type-conversion c++23 explicit-object-parameter

来自提案的 \xc2\xa74.2.7 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#pathological-cases

\n

它说:

\n
\n

这些更不可能是真正有用的代码。在此示例中,B既不能转换为A也int,因此这两个函数甚至都不能使用普通成员语法调用。但是,您可以获取指向此类函数的指针并通过该指针调用它们。(&B::bar)(42)有效,如果奇怪,请致电。

\n
\n

但是,它没有指定标准是否不允许将 type-of-self 的显式对象参数隐式转换为特定的另一种类型。

\n
struct A { };\nstruct B {\n    void foo(this A&);\n    void bar(this int);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

这是否意味着:

\n
struct A { };\nstruct B {\n  operator A() const noexcept;\n  void foo(this A);\n};\n\n// ...\n// \'&B::foo\' is of type function pointer not pointer to member function\n// because it uses explicit object parameter.\n(&B::foo)(A{}); \n(&B::foo)(B{});\nB{}.foo(); // will work?\n
Run Code Online (Sandbox Code Playgroud)\n

将工作?

\n

在另一种情况下,这是一个 lambda。由于 lambda 的类型是不可言说的并且始终是相关的。那上面的案例呢?(这个无捕获 lambda 可转换为int(*)(int, int, int))

\n
auto fib = [](this int(* self)(int, int, int), int n, int a = 0, int b = 1) {\n  return n == 0 ? a : n == 1 ? b : self(n - 1, b, a + b);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

鉴于:

\n
\n

非成员函数、静态成员函数和显式对象成员函数与函数指针类型或函数类型引用的目标匹配。非静态隐式对象成员函数与指向成员函数类型的指针匹配。([over.match.viable] \xc2\xa712.2.3)

\n
\n
\n

在所有上下文中,当转换为隐式对象参数或转换为赋值运算的左操作数时,仅允许标准转换序列。[注意:当转换为显式对象参数时,如果有的话,允许用户定义的转换序列。- 尾注] ([over.best.ics] \xc2\xa712.2.4.2)

\n
\n

Bar*_*rry 5

对于你的第一个问题:

\n
struct A { };\nstruct B {\n  operator A() const noexcept;\n  void foo(this A);\n};\n\nB{}.foo(); // will work?\n
Run Code Online (Sandbox Code Playgroud)\n

是的。候选查找将找到B::foo,它或多或少地计算为foo(B{}),由于转换函数,它是有效的。您在[over.ics.best]/7中引用的注释中明确指出了这一点:

\n
\n

[注5:当转换为显式对象参数时,如果有的话,允许用户定义的转换序列。\xe2\x80\x94尾注]

\n
\n
\n

对于这一点,我实际上并不完全确定:

\n
auto fib = [](this int(* self)(int, int, int), int n, int a = 0, int b = 1) {\n  return n == 0 ? a : n == 1 ? b : self(n - 1, b, a + b);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

它似乎不太可能有用,你可能永远不应该这样做,所以我不知道它是否真正有效是否重要。但也不确定这对于这样的例子意味着什么:

\n
struct C {\n    C(auto);\n    void f();\n};\n\nauto lambda = [](this C c) { c.f(); }; // OK?\n
Run Code Online (Sandbox Code Playgroud)\n

如果 this 可以转换为函数指针,那么函数指针到底是什么类型?如果是void(*)(),那么C我们要调用哪个f()?所以它必须是这样void(*)(C),在这种情况下,该fib示例肯定不起作用,因为不可能以匹配的方式非通用地拼写函数指针类型。

\n