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!