我能否使隐式初始化为0的过载?

8

有没有可能写一个类使得以下代码是有效的:

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); 是有效的吗? - Luchian Grigore
@LuchianGrigore:它们在语义上是相同的吗?如果是,我猜我可以声明它无效。 - Eric
1
也许你可以尝试使用一个接受 std::nullptr_t 的构造函数(仅供参考...) - gx_
如果 xconst int x = 0;,你是否希望 a 的初始化成功? - jxh
也许这个链接会有用:https://dev59.com/o0_Sa4cB1Zd3GeqP-jkL https://dev59.com/_FvUa4cB1Zd3GeqPyOyE?lq=1 - Suma
4个回答

5
如果您不介意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会使其失效。然而,在那种情况下,它应该比指针构造函数更好。


0
Foo e(1); 

将调用以int为参数的Foo的非显式构造函数。 实质上,这行代码将尝试使用此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

不,直接初始化与复制初始化。 - Luchian Grigore
1
如何使用 explicit Foo(int);Foo(nullptr_t); - gx_

-1

我有一个想法:

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

这个表现是否合理?


2
那甚至不能编译。就重载决议而言,一个 const uint32_t 参数和一个 uint32_t 参数是一样的东西。 - Sebastian Redl

-1

我承认我还没有完全掌握C++11的rvalue语义,但这似乎可以实现你想要的功能:

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
@eric 啊,我没意识到。你说 Foo e(1); 应该是有效的 :/ - Oktalist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接