如何区分 C++ 中的 implicit/explicit 构造函数调用?

How to differentiate implicit/explicit constructor calls in C++?

我正在尝试检测何时调用显式构造函数调用与隐式构造函数调用。

假设我们有一个 class Foo:

class Foo{
public:
    Foo(int _val) : val(_val){};
private:
    int val;
}

void bar(Foo f){
   ...
}

我们可以这样调用 bar:

Foo f(10);
bar(f);

或喜欢:

bar(10); // implicit initialization

现在,我知道如果我们明确构造函数:

class Foo{
public:
    explicit Foo(int _val) : val(_val){};
private:
    int val;
}

然后我们可以得到这个错误:

bar(10); // ERROR! implicit initialization not allowed.

所以我想也许可以有一种变通方法来检测显式调用与隐式调用,如下所示:

class Foo{
public:
    explicit Foo(int _val) : val(_val){}; // calling Foo f(10); bar(f);
    Foo(int _val) : val(_val){}; // calling bar(10);
private:
    int val;
}

但正如预期的那样,它 returns "cannot be overloaded",因为函数签名不明确。

最终结果应该是这样的:

class Foo{
public:
    explicit Foo(int _val) : val(_val), flag(true) {}; // calling Foo f(10); bar(f);
    Foo(int _val) : val(_val), flag(false) {}; // calling bar(10);
private:
    int val;
    bool flag;
}

void bar(Foo f){
    std::cout << "f's flag set to : " << f.flag << std::endl;
}

Foo f(10);
bar(f); // f's flag set to : 1
bar(10); // f's flag set to : 0

但很明显,由于上述尝试是徒劳的,而且我也没有更好的主意,我想知道 是否有可能在 C++ 中做到这一点。如果不是,那也没关系。

So I thought perhaps there could be a workaround to detect an explicit call vs. implicit, like this:

不,这不可能。如果这纯粹是出于好奇,那么你就有了答案。如果您正在尝试克服真正的问题,您可能想要 post 真正的问题。

it is even possible to do this in C++?

没有.

如您所见,重载歧义是一个问题,这使您无法知道调用的是隐式构造函数还是显式构造函数。

人们可能会假设 在您的情况下 可以通过留意显式构造函数所需的副本来知道调用了哪个构造函数(与隐式的),但这并不是那么可靠,因为一个好的编译器可以利用 Copy Elision 并绕过复制操作。

因此,如果我们依靠我们的复制假设来确定显式构造函数是否被调用,我们可能会收到假阴性,以防复制实际上被删除。

一般来说,复制构造函数是允许省略的,它们应该不会有副作用。

这很简单,但解决方案是在被调用的函数中,而不是在您正在创建的对象中。

void bar(Foo&) { ... }
void bar(Foo&&) { ... }

Foo f(10);
bar(f);  // calls the first one
bar(10); // calls the second one