当前位置: 首页 > 知识库问答 >
问题:

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

史英飙
2023-03-14

来自标书§4.2.7http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#pathological-案例

它说:

这些更不可能是真正有用的代码。在此示例中,B既不能转换为A也不能转换为int,因此这些函数甚至都不能使用普通成员语法调用。但是,您可以获取指向此类函数的指针并通过该指针调用它们。

然而,它并没有规定标准是否允许自隐式转换为特定其他类型的类型的显式对象参数。

struct A { };
struct B {
    void foo(this A&);
    void bar(this int);
};

这是否意味着:

struct A { };
struct B {
  operator A() const noexcept;
  void foo(this A);
};

// ...
// '&B::foo' is of type function pointer not pointer to member function
// because it uses explicit object parameter.
(&B::foo)(A{}); 
(&B::foo)(B{});
B{}.foo(); // will work?

将工作?

在另一种情况下,这里是lambda。因为lambda的类型是难言的并且总是依赖的。上面的情况如何?(这个无资本的lambda可转换为int(*)(int, int, int)

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

鉴于:

非成员函数、静态成员函数和显式对象成员函数匹配函数指针类型的目标或对函数类型的引用。非静态隐式对象成员函数匹配指针到成员函数类型的目标。([over.match.viable]§12.2.3)

在所有上下文中,当转换为隐式对象参数或转换为赋值操作的左操作数时,只允许使用标准转换序列。[注:当转换为显式对象参数时,如果有,允许用户定义的转换序列。-结束注]([超过最佳ics]§12.2.4.2)


共有1个答案

寿阳华
2023-03-14

对于第一个问题:

struct A { };
struct B {
  operator A() const noexcept;
  void foo(this A);
};

B{}.foo(); // will work?

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

[注5:转换为显式对象参数时,如果有,允许用户定义的转换序列。-结束说明]

这一次,我实际上并不完全确定:

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

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

struct C {
    C(auto);
    void f();
};

auto lambda = [](this C c) { c.f(); }; // OK?

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

 类似资料:
  • 这将允许编译现有代码,同时识别当前依赖隐式转换的任何地方,因此可以重写它们以使用显式转换,如果不是,则重写它们以具有正确的行为。 但是,这是不可能的,因为我不能用重载。 除了“使转换显式化,接受调用代码在编写适当的更改之前不会编译”之外,有没有一种方法可以实现类似的效果?

  • 在研究这个问题时,我注意到GCC(V4.7)的实现在取值时移动了参数。下面的代码显示了此行为: 在这里,我们看到执行了的一个副本(这似乎是合理的,因为的参数是由value取的),但接下来有两个移动。由于是在的副本上操作的,因此它移动参数的事实可以看作是一个不重要的实现细节。但是,当将与一起使用时,此行为会引起一些麻烦: 这种行为是否为标准所允许?是否允许移动其参数?如果是这样的话,我们可以将返回的

  • 问题内容: 以下代码 使用V1.7.0_15 编译时没有错误,并且在运行时显示“ false”。但是,Eclipse Juno抱怨“操作数类型对象和布尔值不兼容”。 显然,javac自动装箱原始boolean ,然后通过对象相等(yielding)进行比较和自动装箱,而Eclipse拒绝执行自动装箱。 根据Java语言规范,哪种行为正确?我应该在哪里提交错误? 注意: 如果将的类型更改为,则事情将

  • 本文向大家介绍把对象转换到数字类型是如何转换的?相关面试题,主要包含被问及把对象转换到数字类型是如何转换的?时的应答技巧和注意事项,需要的朋友参考一下 1、如果对象有valueOf方法,则调用该方法,并返回相应的结果; 2、当调用valueOf返回的依然不是数字,则会调用对象的toString方法,并返回相应的结果; 3、否则抛出异常。

  • 从学习Java的第一天起,各种网站和许多老师就告诉我,数组是连续的内存位置,可以存储指定数量的相同类型的数据。 由于数组是一个对象,对象引用存储在堆栈上,而实际对象位于堆中,因此对象引用指向实际对象。 但是当我遇到如何在内存中创建数组的示例时,它们总是显示如下内容: (其中对数组对象的引用存储在堆栈上,并且该引用指向堆中的实际对象,其中还有指向特定内存位置的显式索引) 但是最近我在网上看到了Jav

  • 问题内容: 这是有效的json吗? http://jsonlint.com/表示同意。 http://www.json.org/没有说什么被禁止。 但这显然没有多大意义,对吗?大多数实现可能使用哈希表,因此无论如何都将其覆盖。 问题答案: JSON校验可以在https://www.jsonformatting.com/