Reputation: 59
Im trying to build a vector of type template but keep getting an error
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;
}
I keep receiving the same error -
request for member 'val' in 'a', which is of non-class type 's<std::vector<int>*>()'|
Any advice will be greatly appreciated
Upvotes: 0
Views: 309
Reputation: 48457
s <vector<int>*> arrays();
This does not instantiate an object, it declares a function that returns s<vector<int>*>
, and as a consequence:
cout << arrays << endl;
Tries to print out a function pointer by instantiating your templated operator<<
:
template <typename T>
ostream& operator<< (ostream& os, const T& a){
return os << a.val;
}
with:
T = s<vector<int>*>(*)();
and so, a pointer to function a
does not have the .val
field which triggers the error.
Upvotes: 2
Reputation: 137315
s <vector<int>*> arrays();
Declares a function named arrays
taking no arguments and returning a s<vector<int>*>
. Remove the redundant parentheses or replace them with {}
for C++11. Of course, your s
doesn't support default construction, so you need to give it a default constructor - which can be as simple as giving the constructor a default argument:
s(T a = T())
{
val = a;
}
and it's better to use the member initialization list instead of assignment and take a const ref instead of by value, since T
can be large:
s(const T& a = T()) : val(a) { }
In C++11, you should take by value and move a
into val
instead:
s(T a = T()) : val(std::move(a)) { }
Also,
template <typename T>
ostream& operator<< (ostream& os, const T& a){
return os << a.val;
}
would match everything under the sun. Better to match s
only:
template <typename T>
ostream& operator<< (ostream& os, const s<T>& a){
return os << a.val;
}
Finally,
friend ostream& operator<<(ostream& os, const T& a);
befriends (and declares) a simple function rather than a function template. To befriend the template operator <<
as modified above:
template <typename U>
friend ostream& operator<<(ostream& os, const s<U>& a);
Or even better, remove the template operator and define the friend function inline (inside the class definition) instead:
friend ostream& operator<<(ostream& os, const s<T>& a){
return os << a.val;
}
This is more compact, and also limits friendship to the matching version of operator <<
, rather than all instantiations of the template.
Demo.
Upvotes: 2
Reputation: 2619
The whole problem is that this
ClassName InstanceName();
is not creating an instance of ClassName
using default constructor, but declares a function. In order to do what you wanted (and I presume that is to create instances with default constructors) use syntax
ClassName InstanceName;
So, in order to fix your errors, change
s <string> word();
s <vector<int>*> arrays();
to
s <string> word;
s <vector<int>*> arrays;
and add a default constructor to your class s
.
Upvotes: 1