Calling an aliased-declared base class constructor in a different namespace - c++

I am trying to understand some details of alias-declared classes through C++11's using and how/why this affects a base class constructor call.
Example Code
#include <iostream>
namespace N {
template<typename T>
struct Foo
{
// Foo(){}; // NOTE: If this line is present, error 2 goes away.
Foo(T t):value(t){};
~Foo() = default;
T value;
};
struct BarInt : public Foo<int>
{
BarInt(int t):Foo< int >(t){};
~BarInt() = default;
};
using BarFloat = Foo<float>;
};
struct A : public N::BarInt
{
A(int i=42):BarInt(i){}; //BarInt(i) or N::BarInt(i) doesn't matter here
~A() = default;
};
struct B : public N::BarFloat
{
B(float f=23.0):BarFloat(f){}; //two errors with gcc4.7.2 (with -std=gnu++11)
// B(float f=23.1):N::BarFloat(f){}; //this line seems to work.
~B() = default;
};
int main(int argc, char **argv)
{
A a;
B b;
std::cout << "a's value is "<< a.value << "\n"
<< "b's value is "<< b.value << std::endl;
return 0;
}
gcc 4.7.2 (compiling with -std=gnu++11) generates two errors for this code which I believe to be related (although I do not understand how...)
Error 1
main.cpp: In constructor ‘B::B(float)’:
main.cpp:32:19: error: class ‘B’ does not have any field named ‘BarFloat’
My searches on stackoverflow brought up Is a namespace required when referring to the base class, which mentions injected class name as a starting point for a further search. However, from what I gathered, this explains why I can write the constructor for A the way I did it (i.e. as A(int i=42):BarInt(i){};) and why BarInt(i) does not have to be qualified with the namespace N.
So why doesn't that work with B? According to What is the difference between 'typedef' and 'using' in C++11?, using is the same as a good old typedef, so I guess my question for the first error is how alias-declared class (BarFloat in my example) differ from regular classes (BarInt in my example) in the context of injecting class names. Any pointers are greatly appreciated :)
Error 2
main.cpp:32:29: error: no matching function for call to ‘N::Foo<double>::Foo()’
main.cpp:32:29: note: candidates are:
main.cpp:9:5: note: N::Foo<T>::Foo(T) [with T = double]
main.cpp:9:5: note: candidate expects 1 argument, 0 provided
main.cpp:6:10: note: constexpr N::Foo<double>::Foo(const N::Foo<double>&)
main.cpp:6:10: note: candidate expects 1 argument, 0 provided
This error goes away if I, as already noted in the example code above, introduce an empty Foo() constructor. The question I have, however, is why BarFloat(f) triggers a call to the empty Foo() constructor and, in that case, how BarFloat.value would be possibly set to 23.0.
Post Scriptum
As this is my first post here: Hello stackoverflow and thank you all for the tremendous help you already provided to me through helping others with their problems!

When you inherit from a class, the derived class can access the names of the base class (including the base class name itself) without qualification. You are effectively inheriting the names in the base class. This is why inheriting from N::BarInt allows you to refer to BarInt within A without qualification.
For B, you are inheriting from Foo<double> using the BarFloat alias, but Foo<double> doesn't contain BarFloat, so you don't inherit that name.
The second error is just because of the first failure. Since the compiler didn't see a valid initialization of the base, it is just like you didn't explicitly ininitialize the base at all, so it is forced to initialize it with the default constructor, which you don't have.

Related

At what point in the syntax is a class declared? [duplicate]

This question already has answers here:
How can a class inherit from a template based on itself?
(3 answers)
Closed 5 years ago.
For example, would the following cause any errors during runtime?
template<typename Ty>
struct Foo {
};
// would this work during run time?
struct Bar : public Foo<Bar> {
};
If it does work, is it bad practice? Is it unoptimized?
Bar is declared at the point of struct Bar appearing. It is an incomplete type until the class definition is complete.
Your code is legal and is in fact a known design pattern called Curiously recurring template.
Your code doesn't cause any errors. Its called as curiously recurring template pattern.
It is used to create a specialised base class definition for each of the sub class instead of a common base class definition.
Consider the example:
template<class T>
class Base
{
static int counter;
public:
Base()
{
++ counter;
}
~Base()
{
-- counter;
}
static int getCounter()
{
return counter;
}
};
template<class T>
int Base<T>::counter = 0;
class A : public Base<A>
{
};
class B : public Base<B>
{
};
int main()
{
A a1, a2, a3;
B b1, b2;
cout << "A count is : " << A::getCounter() << endl;
cout << "B count is : " << B::getCounter() << endl;
}
Without curiously recurring template pattern, the output would be 5 and 5 for both classes (A & B)
With the said pattern applied, the output will be 3 and 2 for the A & B classes respectively.
Hope this helps :-)
Just like any other situation where you have a incomplete type (like when a class is forward declared), you cannot use the full object in the template. Logically it cannot be allowed because it would cause infinite recursion trying to populate a data type which includes itself.
template<typename Ty>
struct Foo {
Ty ty1; // <== Not allowed, incomplete type
Ty * ty2; // <== Just fine
Ty & ty3; // <== Just fine
};
struct Bar : public Foo<Bar> {
};
Live: https://godbolt.org/g/sf72Wp
It's no different than a class which uses itself:
Class Foo {
Foo * f;
};
Here is what the OP asked:
For example, would the following cause any errors during runtime?
template<typename Ty>
struct Foo {};
// would this work during run time?
struct Bar : public Foo<Bar> {};
If it does work, is it bad practice? Is it unoptimized?
What is shown in the question is that there is an empty struct Foo that is of a template type. The only thing this struct has is a default ctor & dtor, there is no consumption of stack memory outside of the default ctor & dtor for there are no members. This by itself will compile absolutely fine and will not cause any runtime error. The next line in question struct Bar : Foo<Bar>{} is an empty struct Bar that is not a tamplate type that derives from a template type that happens to be instantiated as a class template of type <Bar> and again Bar has the same operability as Foo because it has only a default ctor & dtor. So this would still not cause any problems at runtime.
Now as for the last question and its two parts. If it does work, is it bad practice? Is it unoptimized?
What do you mean by unoptimized?
If it does work, is it bad practice?
Well this is the more important question...
Why?
It doesn't matter in this context until you start adding components to the classes. As it stand as is with these declarations, there are no executions or instructions happening after and before the ctor & dtor calls. These as they are, are both its declaration & definition since there are no member variables or methods to perform any calculations, comparisons or anything else. There is no existing variable declaration of the class type being instantiated such as in this snippet.
template<typename T> class Foo{};
class Bar : public Foo<Bar> {};
int main () {
Bar bar; // <-- now the default ctor is used and `bar` is now a declared variable
// in memory of type class Bar;
// Next line of code here
return 0;
} // -> default dtor is used
And this should still compile and run because of the fact that as these classes currently stand: bar.* or bar->* where * means any member is meaningless in this context since both classes here have a scope that is completely empty and there is nothing to do or perform.
Now when you start to add members of different types and methods to work on them then some things will work and others wont. For it to work Bar must be a complete type as you can not use an abstract class in this case. There might be a little more involved than this but this is as much as I can answer for this question. I hope this helps and if anyone sees any problems with this answer please leave a reply first as to what is wrong first and then let me address it before just down voting it right a way without giving a word. A negative comment can be more constructive than just a class Boo {};!

C++ Template constructor of a inherited class

From what I understand about inheritance in C++ is that whenever the constructor of a child class is called, constructor of the parent class is called automatically. And as for templated constructors, data type of the template argument is infered automatically i.e. we don't need to specify template arguments separately. The program generates a compilation error which I don't seem to understand.
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
class A{
public:
int x;
int y;
int first(){
return x;
}
int second(){
return y;
}
};
class C{
public:
float a,b;
C(){
a = 0.0f;
b = 0.0f;
}
template<class T>
C(T t){
a = t.first();
b = t.second();
}
};
class D: public C{
public:
float area(){
return a*b;
}
}
int main(){
A a;
a.x = 6;
a.y = 8;
C c(a);
D d(a);
cout<<c.a<<" "<<c.b<<" "<<d.area()<<endl;
}
Compilation error generated
test.cpp: In function ‘int main()’:
test.cpp:56:8: error: no matching function for call to ‘D::D(A&)’
test.cpp:56:8: note: candidates are:
test.cpp:44:7: note: D::D()
test.cpp:44:7: note: candidate expects 0 arguments, 1 provided
test.cpp:44:7: note: D::D(const D&)
test.cpp:44:7: note: no known conversion for argument 1 from ‘A’ to ‘const D&’
I have no idea what is happening here. Any ideas?
D has to pass the constructor argument to C, since you are not using default constructors.
class D : public C {
public:
template <typename T> D (T t) : C(t) {}
float area () { /* ... */ }
};
The reason for the error is that you are trying to construct D with a parameter, but have not declared any constructor that would allow you to do so. Furthermore, you have to pass the parameter into C, otherwise the compiler will use C's default constructor.
The compiler error message can be analyzed like this.
test.cpp:56:8: error: no matching function for call to ‘D::D(A&)’
The compiler is complaining about:
D d(a);
And that it can't figure out how to construct a D when passed something of type A.
It then presents the two choices of constructors it knows about:
test.cpp:44:7: note: D::D()
test.cpp:44:7: note: D::D(const D&)
And it points out that for each one, there is a reason it can't use it. For the first one, it doesn't take any arguments. For the second one, it has no way to convert something of type A into type D.
From what I understand about inheritance in C++ is that whenever the constructor of a child class is called, constructor of the parent class is called automatically.
Careful: The constructor of the parent class is automatically called with the same arguments as the constructor of the child class.
As for the specific problem at hand: There is no constructor declared for class D. You'll get a default constructor and copy constructor as freebies, but not that template-based constructor in class C. Constructors aren't inherited.

c++ and injected base name

The following code does not compile in gcc:
namespace One{
class A{
};
};
namespace Two{
class A{
public:
void what(){
cout << "Two::A says what!" << endl;
}
};
class B : public One::A{
public:
B(){
A xx;
xx.what();
}
};
};
And it gives:
gccbug.cpp: In constructor ‘Two::B::B()’:
gccbug.cpp:23: error: ‘class One::A’ has no member named ‘what’
Now, I was told that this is correct behavior (due to injected base name of One::A making A refer to One::A). However, this code compiles in C# (well, after changing a few things), so this seems to be c++ specific.
What I'm wondering is.. why? Is there a specific purpose for injecting the base name "One::A" as "A"?
The only reason I can think of is that in C++ you are likely to refer to the base class name in the initializer list of the constructor, like this:
namespace Two {
/*...*/
class B : public One::A {
public:
B():A()
{
/*...*/
}
};
}
Of course the purpose then is different from the one in your example, because you actually declare a local variable inside the constructor, whereas in my example, the A() refers to the object of type A that is implicit in the definition of class B due to inheritance.
However, the situation of my example is more likely to occur, so I guess they thought let's not require the namespace to be made explicit in this case. As a consequence, any reference to A without a namespace is interpreted as referring to the base class, rather than any other class named A, even if it is in the same namespace as the declaration of B.
Is there a specific purpose for injecting the base name "One::A" as "A"?
Yes. It is so that you could write this:
namespace N
{
class A
{
A *a;
};
}
In the absence of injected-name, you've to write N::A *a which is not nice.
Note that it is because of injected-name, the following lines are allowed:
A::A *a1; //ok
A::A::A *a2; //ok
A::A::A::A *a3; //ok
A::A::A::A::A *a4; //ok
//and so on
Online demo
By qualifying A with One:: you added the A from namespace one in scope, so the compiler will look there for it's name resolution.

C++ inheritance and function overriding

In C++, will a member function of a base class be overridden by its derived class function of the same name, even if its prototype (parameters' count, type and constness) is different? I guess this a silly question, since many websites says that the function prototype should be the same for that to happen; but why doesn't the below code compile? It's a very simple case of inheritance, I believe.
#include <iostream>
using std::cout;
using std::endl;
class A {};
class B {};
class X
{
public:
void spray(A&)
{
cout << "Class A" << endl;
}
};
class Y : public X
{
public:
void spray(B&)
{
cout << "Class B" << endl;
}
};
int main()
{
A a;
B b;
Y y;
y.spray(a);
y.spray(b);
return 0;
}
GCC throws
error: no matching function for call to `Y::spray(A&)'
note: candidates are: void Y::spray(B&)
The term used to describe this is "hiding", rather than "overriding". A member of a derived class will, by default, make any members of base classes with the same name inaccessible, whether or not they have the same signature. If you want to access the base class members, you can pull them into the derived class with a using declaration. In this case, add the following to class Y:
using X::spray;
That's so called 'hiding': Y::spray hides X::spray.
Add using directive:
class Y : public X
{
public:
using X::spray;
// ...
};
Classes are scopes and a class scope is nested in its parent. You have exactly the same behavior with other nested scopes (namespaces, blocks).
What happen is that when the name lookup searches for the definition of a name, it looks in the current namespace, then in the englobing namespace and so on until it find one definition; the search then stop (that's without taking into account the complications introduced by argument dependent name lookup -- the part of the rules which allows to use a function defined in the namespace of one of its argument).

Overriding a Base's Overloaded Function in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ overload resolution
I ran into a problem where after my class overrode a function of its base class, all of the overloaded versions of the functions were then hidden. Is this by design or am I just doing something wrong?
Ex.
class foo
{
public:
foo(void);
~foo(void);
virtual void a(int);
virtual void a(double);
};
class bar : public foo
{
public:
bar(void);
~bar(void);
void a(int);
};
the following would then give a compile error saying there is no a(double) function in bar.
main()
{
double i = 0.0;
bar b;
b.a(i);
}
In class bar, add
using foo::a;
This is a common 'gotcha' in C++. Once a name match is found in the a class scope, it doesn't look further up the inheritance tree for overloads. By specifying the 'using' declaration, you bring all of the overloads of 'a' from 'foo' into the scope of 'bar'. Then overloading works properly.
Keep in mind that if there is existing code using the 'foo' class, its meaning could be changed by the additional overloads. Or the additional overloads could introduce ambiguity and and the code will fail to compile. This is pointed out in James Hopkin's answer.
That is the way the language used to work. Prior to the using keyword, if you overrode one overloaded function, you had to overload them all:
class bar : public foo
{
public:
bar(void);
~bar(void);
a(int);
a(double d) { foo::a(d); } // add this
}
This annoyed enough people that the language committee added the using feature, but some old habits die hard; and the habitués† have a good argument.
As James Hopkins points out, by adding using, the programmer is expressing the intention that the derived class will, without warning, add any future overrides of foo::a() to its list of acceptable signatures.
Here is an example of what he describes:
#include <iostream>
class Base {
public:
virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
// virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
virtual ~Base() {}
};
class Derived : public Base {
public:
// using Base::f; // (2)
void f(double) { std::cout << "Derived::Double!" << std::endl; }
};
int main(int, char **) {
Derived d;
d.f(21);
return 0;
}
The output will be "Derived::Double!" because the compiler will promote the integer argument to a double. g++ 4.0.1 -Wall will not warn that this promotion occurred.
Uncomment (1) to simulate a future change to Base adding the method Base::f(int). The code compiles, again without warning even with -Wall, and "Derived::Double!" remains the output.
Now uncomment (2) to simulate a decision by the Derived programmer to include all Base::f signatures. The code compiles (without warnings), but the output is now "Base::Int!".
—
† I cannot think of an English word for "those who have the habit" and "addicted" is much too strong.
It is by design. Overload resolution is restricted to a single scope. It prevents some nasty cases of valid code changing meaning when additional functions are added to a base class or to namespace scope.