Im пытается создать вектор шаблона типа, но продолжать получать ошибку
template<class T>
struct s{
T val;
public:
s(T a)
{
val = a;
};
friend ostream& operator<<(ostream& os, const T& a);
};
template <typename T>
ostream& operator<< (ostream& os, const T& a){
return os << a.val;
}
int main()
{
s <double> names(4) ;
s <int> figure(7);
s <string> word();
s <vector<int>*> arrays();
cout << names << endl;
cout << figure << endl;
cout << arrays << endl;
return 0;
}
Я продолжаю получать ту же ошибку -
request for member 'val' in 'a', which is of non-class type 's<std::vector<int>*>()'|
Любые советы будут высоко оценены
s <vector<int>*> arrays();
Это не создает экземпляр объекта, он объявляет функцию, которая возвращает s<vector<int>*>
, и, как следствие:
cout << arrays << endl;
Пытается распечатать указатель на функцию, создав экземпляр вашего шаблонного operator<<
:
template <typename T>
ostream& operator<< (ostream& os, const T& a){
return os << a.val;
}
с:
T = s<vector<int>*>(*)();
и поэтому указатель на функцию a
не имеет поля .val
которое вызывает ошибку.
T& get() { return val; } const T& get() const { return val; }
, а если быть точным, теперь у вас есть T = std::vector<int>*
, поэтому val
- указатель на вектор целых
s <vector<int>*> arrays();
Объявляет функцию с именем arrays
, не принимает аргументов и возвращает s<vector<int>*>
. Удалите лишние круглые скобки или замените их на {}
для С++ 11. Конечно, ваш s
не поддерживает конструкцию по умолчанию, поэтому вам нужно дать ему конструктор по умолчанию - это может быть так же просто, как дать конструктору аргумент по умолчанию:
s(T a = T())
{
val = a;
}
и лучше использовать список инициализации членов вместо назначения и принять const ref вместо значения, поскольку T
может быть большим:
s(const T& a = T()) : val(a) { }
В С++ 11 вы должны взять по значению и переместить a
в val
вместо:
s(T a = T()) : val(std::move(a)) { }
Также,
template <typename T>
ostream& operator<< (ostream& os, const T& a){
return os << a.val;
}
будет соответствовать всему, что под солнцем. Лучше всего соответствовать только s
:
template <typename T>
ostream& operator<< (ostream& os, const s<T>& a){
return os << a.val;
}
В заключение,
friend ostream& operator<<(ostream& os, const T& a);
подружится (и объявит) простую функцию, а не шаблон функции. Чтобы подружиться с operator <<
шаблона operator <<
как было изменено выше:
template <typename U>
friend ostream& operator<<(ostream& os, const s<U>& a);
Или даже лучше, удалите оператор шаблона и определите функцию friend inline (внутри определения класса):
friend ostream& operator<<(ostream& os, const s<T>& a){
return os << a.val;
}
Это более компактно, а также ограничивает дружбу подходящей версией operator <<
, а не все экземпляры шаблона.
Демо.
Вся проблема в том, что это
ClassName InstanceName();
не создает экземпляр ClassName
с использованием конструктора по умолчанию, но объявляет функцию. Чтобы делать то, что вы хотели (и я полагаю, что это создание экземпляров со стандартными конструкторами), используйте синтаксис
ClassName InstanceName;
Итак, чтобы исправить ваши ошибки, измените
s <string> word();
s <vector<int>*> arrays();
в
s <string> word;
s <vector<int>*> arrays;
и добавьте конструктор по s
умолчанию для вашего класса s
.