我可以将隐式初始化重载为 0 吗?

Posted

技术标签:

【中文标题】我可以将隐式初始化重载为 0 吗?【英文标题】:Can I overload an implicit initialization to 0? 【发布时间】:2013-06-17 12:17:50 【问题描述】:

是否可以编写一个使这些有效的类:

Foo a;
Foo b = 0;
Foo c = b;
Foo d(0);
Foo e(1);
Foo f = Foo(1);

但这些不是:

int x;
Foo a = x;
Foo b = 1;
Foo c = 2;
//etc

基本上,我的规则是“常量0 可以隐式转换为Foo,但没有其他值”

【问题讨论】:

Foo e(1); 呢?这怎么有效? @LuchianGrigore:它们在语义上是否相同?如果是这样,我想我可以宣布无效。 也许您可以尝试使用带有std::nullptr_t 的构造函数(只是一个想法......) 如果xconst int x = 0;,你希望a 的初始化成功吗? 也许这可能有用:***.com/questions/3299834/…***.com/questions/7658060/… 【参考方案1】:
Foo e(1); 

将调用 Foo 的非显式构造函数,以 int 作为参数。 本质上,这一行将通过尝试使用此 int 构造函数将 int 转换为 Foo 来做同样的事情。

Foo b = 1;

您不能阻止直接处理该 int 的某些值。 如果你有你的构造函数explicit,你也不能写下一行。

Foo b = 0;

gx_ 正确地指出 0 可以转换为 std::nullptr_t。 以下内容将根据您的意图起作用。

Foo(std::nullptr_t x) : member(0)  
explicit Foo(int c) : member(c)  
// ...
Foo a = 0; // compiles
Foo b = 1; // doesn't compile

// Note:
int do_stuff (void)  return 0; 
Foo c = do_stuff(); // doesn't compile

【讨论】:

不,直接与复制初始化。 一个explicit Foo(int); 加上一个Foo(nullptr_t); 怎么样?【参考方案2】:

我的一个想法是:

Foo(const uint32_t c) : member(0)  static_assert(c == 0, "Nope"); 
explicit Foo(uint32_t c) : member(c)  

这样做是否合理?

【讨论】:

那甚至无法编译。就重载解析而言,const uint32_t 参数和uint32_t 参数是一回事。【参考方案3】:

如果您不介意 Foo b = nullptr; 工作,那么很容易破解。有一个来自int 的显式构造函数和一个来自std::nullptr_t 的隐式构造函数。

如果您确实介意这种工作,我不确定它是否可能。区分文字0 和其他整数文字的唯一方法是前者隐式转换为指针和nullptr_t。所以nullptr 会更喜欢nullptr_t 参数而不是指针参数,因此通过拥有两个构造函数,您可以过滤掉nullptr 参数。但是,0 到指针的转换和 nullptr_t 的转换等级相同,因此这会导致 0 参数不明确。

嗯......这样的事情可能会起作用:

class Foo 
  struct dummy;
public:
  explicit Foo(int); // the version that allows Foo x(1);
  Foo(dummy*); // the version that allows Foo x = 0;
  template <typename T,
            typename = typename std::enable_if<
                std::is_same<T, std::nullptr_t>::value>::type>
  Foo(T) = delete; // the version that prevents Foo x = nullptr;
;

我还没有真正尝试过这个。理论上,模板应该只在参数为nullptr 时参与重载决议,否则 SFINAE 会杀死它。但是,在这种情况下,它应该比指针构造函数更好。

【讨论】:

【参考方案4】:

我承认我还没有完全掌握 C++11 的右值语义,但这似乎是你想要的:

class Foo

    public:
    Foo(int&&) 
;

int main()

    Foo a(123);
    int x = 123;
    Foo b(x); // error here, line 11
    return 0;

结果:

prog.cpp:11: 错误:无法将‘int’左值绑定到‘int&&’

欢迎评论,如果此代码有任何我没有注意到的警告,或者您可以向我保证它没有。

【讨论】:

有趣,但我的目标是x == 0的具体案例; @eric 啊,没有意识到这一点。你说Foo e(1); 应该是有效的:/

以上是关于我可以将隐式初始化重载为 0 吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何将隐式参数传递给隐式类

在 C++0x 中,非静态数据成员初始化器会覆盖隐式复制构造函数吗?

将隐式等待和显式等待结合在一起会导致意外的等待时间

JVM之对分配参数详解

JAVA学习笔记-this隐式参数

jvm 虚拟机参数_堆内存分配