Я пытаюсь понять некоторые детали классов, объявленных псевдонимами, через using С++ 11 и как/почему это влияет на вызов конструктора базового класса.
Пример кода
#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 (компиляция с -std=gnu++11) генерирует две ошибки для этого кода, которые, как мне кажется, связаны (хотя я не понимаю, как...)
Ошибка 1
main.cpp: In constructor ‘B::B(float)’:
main.cpp:32:19: error: class ‘B’ does not have any field named ‘BarFloat’
Мои поиски в stackoverflow привели к Требуется ли пространство имен при ссылке на базовый класс, который упоминает имя внедрённого класса в качестве отправной точки для дальнейшего поиска. Однако из того, что я собрал, это объясняет, почему я могу написать конструктор для A так, как я это сделал (то есть как A(int i=42):BarInt(i){};), и почему BarInt(i) не нужно квалифицировать с помощью пространства имен N.
Так почему же это не работает с B? Согласно В чем разница между "typedef" и " using' в C++11?, using совпадает со старым добрым typedef, поэтому я думаю, что мой вопрос для первой ошибки заключается в том, как класс, объявленный псевдонимом (BarFloat в моем примере), отличается от обычных классов (BarInt в моем примере) в контексте внедрения имен классов. Любые указатели приветствуются :)
Ошибка 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
Эта ошибка исчезает, если я, как уже отмечалось в примере кода выше, ввожу пустой конструктор Foo(). Однако у меня есть вопрос, почему BarFloat(f) вызывает вызов пустого конструктора Foo() и, в этом случае, как BarFloat.value может быть установлено на 23.0.
Пост скриптум
Поскольку это мой первый пост здесь: Привет, stackoverflow, и спасибо всем за огромную помощь, которую вы уже оказали мне, помогая другим с их проблемами!