According to the answers I obtained here, the code below is ill-formed, notwithstanding the fact that clang
and vs2015
accept it.
#include <iostream>
class A {
public:
A() { std::cout << "A()" << '\n'; }
};
int main()
{
A::A();
}
Nevertheless the code below appears to work in all 3 compilers (see live example). AFAICT, according to [class.qual/2] the code is ill-formed. Or am I missing something here?
#include <iostream>
struct B { B() { std::cout << "B()" << '\n'; } };
struct A : public B { };
int main()
{
A::B();
}
Also, according to [class.qual]/2, the code below is well-formed and in this case, all 3 compilers produce the expected output (see example here).
include <iostream>
struct B { B() { std::cout << "B()" << '\n'; } };
struct A : public B { using B::B; A() { std::cout << "A()" << '\n'; } void f() { B(); } };
int main()
{
A a;
a.f();
}
Output:
B()
A()
B()
But I'd like to know what is the usefulness of a using-declaration naming a constructor, as the one (using B::B;
) in class A
above. Note that this using-declaration is totally irrelevant in this case, no matter whether B
is a base class of A
, or not.
I think that the your second sample is well-formed. The rule in [class.qual]/2
states that the name refers to the constructor if the name specified after the nested-name-specifier when looked up in C
is the injected-class-name of C
. In the case of A::B
, the name specified after the nested-name-specifier is the injected-class-name of B
(visible due to inheritance), not A
. In this case, A::B
unambiguously names a type, A::B()
creates a temporary B
instance.
Using-declarations naming constructors can be useful to promote base-class constructors which take arguments:
struct B { B(int a) { std::cout << "B " << a << '\n'; } };
struct A : public B { using B::B; };
int main()
{
A a{1}; //would not be valid without the using-declaration
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With