I have a vector of type template class and I am trying to print it, but getting a weird error.
Here is my class:
template <typename VertexType, typename EdgeType> class Vertex{
private:
typedef std::vector<std::pair<int, EdgeType> > VertexList;
std::vector<Vertex<VertexType, EdgeType>> Vertice;
public:
void Add(Vertex);
};
Add Method and Print Statement:
template <typename VertexType, typename EdgeType> void Vertex<VertexType, EdgeType> ::Add(Vertex v)
{
int count = 5;
//std::vector<string>temp;
for(int i=0; i<count; i++)
Vertice.push_back(v);
for(int i=0; i<Vertice.size(); i++)
cout<< Vertice[i] <<endl;
}
Main() Method:
int main()
{
Vertex<std::string, std::string> v1;
v1.Add(v1);
std::getchar();
}
Error am getting is:
error C2679: binary '<<' : no operator
found which takes a right-hand operand
of type 'Vertex'
(or there is no acceptable conversion)
You aren't defining an operator << anywhere. You should define it like this out of your class :
template <typename VertexType, typename EdgeType>
std::ostream& operator << (std::ostream& out, const Vertex<VertexType,EdgeType>& v);
// implementation
template <typename VertexType, typename EdgeType>
std::ostream& operator << (std::ostream& out, const Vertex<VertexType,EdgeType>& v) {
// print whatever you want that represents your vertex
// please don't forget to return this reference.
return out;
}
Also, having a class with a vector of instances of it inside is a call for trouble. Remember that "vector<Vertice<VertexType,EdgeType> >" is an array of instances, not an array of references. If you want a array of 'references' to Vertex, use an array of pointers.
And consider using boost's graph library instead of redefining yet another one and coming to all pitfall associated with graphs (like memory management for instance). The boost library also have some useful algorithms that you could want to use..
Well, implement template <class V, class E> std::ostream& operator<<(std::ostream& os, const Vertex<V,E> &vertex) as a static friend of Vertex. It's pretty much what the compiler tells you...
Related
I am having trouble with the two-phase look-up as specified by the standard and (correctly) implemented by clang in connection with an overload of operator<< for std::ostream and std::vector.
Consider a very generic template function which shifts its argument into a stream (really useful only with recursion, but the simple example is enough to trigger the problem):
// generic.h
template<typename Stream, typename Arg>
void shift(Stream& s, Arg& arg) { s << arg; }
This generic.h may be used throughout a project. Then in some other file, we want to output a std::vector, so we define an overload
// vector.h
#include <iostream>
#include <vector>
std::ostream& operator<<(std::ostream& s, std::vector<int> const& v) {
for(auto const& elem : v) { s << elem << ", "; }
return s;
}
And the main file, we firstly (indirectly) use the generic.h and then, due to some other include, the vector overload:
// main.cpp
#include "generic.h"
#include "vector.h"
int main() {
std::vector<int> v{1,2,3,4,5};
shift(std::cout, v);
}
This code is accepted by GCC (5.4.0) and ICC (16.0), but clang complains call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent lookup.
The annoying thing is that clang is right and I’d like to fix this in my code. There are as far as I can see three options:
Move the definition of operator<< before shift(). This has the disadvantage that when including some (possibly other) files which indirectly include generic.h and vector.h, one would also have to take care to order them correctly.
Use a custom namespace, import everything needed from std into that namespace and define the operator on the new-namespace classes inside that namespace, so that ADL can find it.
Define operator<< in the std namespace. I think this is undefined behaviour.
Did I miss any option? What would be the best way in general to define overloads for functions of std-only classes (the issue does not exist if I want to shift NS::MyClass, since then I can just define the operator in NS).
Don't overload operators for types you don't control, such as:
std::ostream& operator<<(std::ostream& s, std::vector<int> const& v);
Instead create a tiny adaptor class and define the operator for that, for example:
template<typename T> struct PrintableVector {
std::vector<T> const* vec;
}
template<typename T>
std::ostream& operator<<(std::ostream& s, PrintableVector<T> v) {
for(auto const& elem : *v.vec) { s << elem << ", "; }
return s;
}
That can be used like:
shift(std::cout, PrintableVector<int>{&v});
You can put the adaptor in whatever namespace you like, and put the overloaded operator in the same namespace so it can be found by ADL.
That avoids lookup problems, doesn't require adding anything to namespace std, and doesn't try to uniquely define what it means to print a vector<int> (which might cause problems in other parts of the program if some other code assumes vectors are not printable, or tries to define its own overloads for them).
I followed Jonathan’s advice and used a wrapper Printable<> to define the operator<<. By making this wrapper also implicitly-convertible to the original type, I can handle both cases where only Printable<T> is printable as well as those were also T itself was printable. Code as follows:
template<typename T>
struct Printable {
T const& ref;
Printable(T const& ref) : ref(ref) { }
operator T const& () { return ref; }
};
template<typename T>
Printable<T> printable(T const& in) { return Printable<T>(in); }
template<typename Stream, typename Arg>
void shift(Stream& s, Arg& arg) {
s << printable(arg);
}
#include <iostream>
#include <vector>
std::ostream& operator<<(std::ostream& out, Printable<std::vector<int> > const& v) {
for(auto const& elem : v.ref) { s << elem << ", "; }
return s;
}
struct MyClass { };
std::ostream& operator<<(std::ostream& s, MyClass const& m) {
return s << "MyClass\n";
}
int main() {
std::vector<int> v{1,2,3};
MyClass m;
shift(std::cout, v);
shift(std::cout, m);
}
This has the advantage that at the point of use in the call to shift(), I don’t have to care what sort of type my variable has. Only in the definition of operator<< for classes I have to be careful as well as when using such an operator.
I'm currently working on implementing some mathematical base operations and try to avoid using third party libraries as much as possible. I'm stuck at overloading the operator* for the multiplication of a Scalar*Vector and Vector*Scalar. The current code for the dot product of Scalar*Vector:
#include <vector>
#include <type_traits>
template<class Vector, class Scalar>
typename std::enable_if<std::is_floating_point<Scalar>::value, Vector>::type operator*
(
const Scalar &a,
const Vector &b
)
{
return Vector
(
a*b[0],
a*b[1],
a*b[2]
);
}
int main()
{
const std::vector<double> v1({1,2,3});
const double s1(2);
const auto result(s1*v1);
std::cout<< result << std::endl;
}
The compiler error message is:
error: invalid operands to binary expression ('double' and 'const std::vector')
Any advises on how to overload the * operator, so that both dot-products are possible? I do not intend to implement these two operators in a custom vector class, as overloaded operators. Rather than that, I aim for the templated operator.
I've found a great explanation here and used it to adjust it for the vector operations. In the vector class header file, you basically define via the struct is_vector that anything of type T is not a vector by default. In the following a all types that can act as a vector have to be listed explicitely, such as std::vector.
#include <vector>
#include <type_traits>
template <typename T>
struct is_vector
{
static const bool value = false;
};
template <>
struct is_vector< std::vector >
{
static const bool value = true;
};
template <class Vector>
typename std::enable_if<std::is_vector<Vector>::value, double>::type
operator*(const Vector &a, const Vector &b);
And in the executable, the code looks the same.
int main()
{
const std::vector<double> v1({1,2,3});
const double s1(2);
const auto result(s1*v1);
std::cout<< result << std::endl;
}
I am writing a template class function comparing std::strings. std::string is the template parameter. My problem is that I can't compare two const string with "==" operator, then I think I create two non-const temporary string variables to performe the comparation, but it still can't compile. Don't know why.
class VGraph is instanced as VGraph<std::string, std::string> myGraph;
template <typename V, typename E>
size_t VGraph<V, E>::find(const V& vert)
{
V temp = vert; // (1)
for (size_t i=0; i<graph.size(); i++)
{
V noneConst = graph[i].getVertex(); // (2)
if (temp==noneConst)// I think broblem is here, and tried to fix using (1)(2)
return i;
}
return graph.size();
}
Prototype of related function
template <typename V, typename E>
const V& VVertex<V, E>::getVertex();
You probably forgot an explicit:
#include <string>
The std::string class is defined by a another header you included, but not the operator ==.
I'm trying to overload the + operator in a forest class, a forest being a collection of trees, and the + operator is supposed to combine two forests into one. I have the following code as my class definition:
template<typename NODETYPE>
class Forest
{
public:
friend Forest& operator+<>(Forest&, Forest&);
friend ostream& operator<<<>(ostream&, const Forest&);
friend istream& operator>><>(istream&, Forest&);
Forest();
Forest( const Forest& otherForest);
~Forest();
void nodes(int&) const;
private:
ForestNode<NODETYPE> *root;
ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};
The following is my implementation of operator+:
template<typename NODETYPE>
Forest& operator+<>(Forest& f1, Forest& f2)
{
f3 = new Forest();
f3.root = *f1.*root;
f3.root.sibling = *f2.*root;
*f1.root = 0;
*f2.root = 0;
return f3;
}
I get the following error on compile:
|28|error: expected constructor, destructor, or type conversion before '&' token|
line 28 refers to the signature of my operator+ implementation.
I think to correct it i am supposed to add to the return type, giving:
template<typename NODETYPE>
Forest<NODETYPE>& operator+<>(Forest& f1, Forest& f2)
{
f3 = new Forest();
f3.root = *f1.*root;
f3.root.sibling = *f2.*root;
*f1.root = 0;
*f2.root = 0;
return f3;
}
But that gives me the following errors:
|28|error: declaration of 'operator+' as non-function|
|28|error: missing template arguments before '&' token|
|28|error: 'f1' was not declared in this scope|
|28|error: missing template arguments before '&' token|
|28|error: 'f2' was not declared in this scope|
Can anyone help me with this? I'd be very very thankful.
The key to writing operator+ is don't write operator+. Instead, write a copy ctor and operator+=:
template<class NodeType>
struct Forest {
//...
Forest(Forest const &other);
//...
Forest& operator+=(Forest const &other) {
// code here
return *this;
}
//...
};
Now we add operator+:
template<class NodeType>
struct Forest {
//...
friend Forest operator+(Forest a, Forest const &b) {
a += b;
return a;
}
//...
};
And that's it! Copying is usually straight-forward (sometimes by being disallowed) and it may be simpler to think in terms of += than + (you have two objects and mutate one, rather than create a third object out of two). This pattern for op+ works with any similar type, and even for similar operators such as -, *, and /.
Operator overloading can be a good or a bad thing. Good when it leads to simpler looking code. Bad when it leads to writers either overloading with incorrect semantics (yet a solution that compiles) or where the intuitive way to use the operator leads to highly inefficient code.
Note the latter statement can apply to std::string too, which could potentially make large numbers of copies, and which is why the C++03 standard states that a string does not have to be stored internally in a contiguous buffer (in the old days they used copy-on-write references to and could store such references to both strings being concatenated until required. Subsequently it was found to be non-threadsafe and making it so was more costly than simply copying the buffer so now they copy every time and are inefficient again).
(Note that the C++11 standard which recognises threading and atomic issues ensures that the underlying does need to be contiguous and null-terminated to make read operations safe).
The correct signature of operator+ (in the case all are the same type) is as follows:
T operator+( const T&, const T& );
As a member function it would be:
class T
{
// make public if necessary
T operator+( const T& rhs ) const;
};
You can implement operator+ automatically as a template whenever operator += is available with
template<typename T, typename R>
T operator+( const T& lhs, const R& rhs )
{
T copy(lhs);
return copy += rhs;
}
If you want to declare an overloaded operator of your template as a friend, this is the correct way to do it. I will show it with operator<<
// first some forward declarations, assume ostream already declared with #include <iosfwd> minimum
template< typename T > class Forest;
template< typename T > std::ostream & operator<<( std::ostream & os, const Forest<T> & for );
template< typename T> class Forest
{
friend std::ostream& operator<< <>( std::ostream&, const Forest<T> & );
//rest of class Forest
};
template< typename T >
std::ostream & operator<<( std::ostream& os, const Forest<T> & forest )
{
// implement
return os;
}
You would apply a similar technique to any other external function you wish to declare as a friend to your class, i.e.
Forwardly declare your class as a template
Forwardly declare the method as a template function
Make the function a friend using <> before the opening parentheses denoting the parameters
Implement the function after your class.
You have to provide a template arguments for all Forest parameters.
template<typename NODETYPE>
Forest<NODETYPE> operator+(Forest<NODETYPE>& f1, Forest<NODETYPE>& f2)
Also, consider making the arguments const references to make sure you do not manipulate them.
There are several questions on stackoverflow regarding friend function templates. The C++ FAQ also has a page on them that explains some basics.
You can define an operator+ template as follows:
template< class NodeType >
Forest<NodeType> operator+( Forest<NodeType> const& f1, Forest<NodeType> const& f2)
{
// Implementation.
}
Cheers & hth.,
Hey, I'm getting a linker error LNK2019: unresolved external symbol when trying to use an overloaded + operator. I'll show you snip-its from the class, and how I'm using it in main. If you need to see more, let me know, I'm just going to try and keep things concise.
/** vec.h **/
#ifndef __VEC_H_
#define __VEC_H_
#include <iostream>
#include <vector>
namespace xoor{
template<typename T>
class vec{
public:
inline friend vec<T> operator + (const vec<T>&, const vec<T>&);
inline const vec<T>& operator += (const vec<T>&);
private:
std::vector<T> m_index;
}; // Vec.
template<typename T>
vec<T>& operator + (const vec<T>& a, const vec<T>& b){
vec<T> product = a;
product += b;
return product;
} // Addition.
template<typename T>
const vec<T>& vec<T>::operator += (const vec<T>& v){
for (unsigned short i =0; i < m_index.size(); ++i){
if (i >= v.size())
break;
m_index[i] += v.getIndex()[i];
}
return * this;
} // Addition Compound.
} // xoor
#endif // __VEC_H_
Note that I've got [] overloaded as well, so I'm just accessing parts of m_index with it. getIndex() just returns m_index. And size() returns m_index.size()
/** main.cpp **/
#include <iostream>
#include "vec.h"
void testHook();
int main(){
testHook();
system("PAUSE");
return 0;
}
void testHook(){
using namespace xoor;
vec<double> vA(3); // passing 3 for 3 elements
vec<double> vB(3);
// v + v
std::cout << "\n\tA + B = ";
vec<double> vAB(3);
vAB = vA + vB; // PRODUCES THE LNK2019
vAB.print(std::cout); // Outputs the vec class to the console.
}
Error Message:
Error 1 error LNK2019: unresolved external symbol "class xoor::vec<double> __cdecl xoor::operator+(class xoor::vec<double> const &,class xoor::vec<double> const &)" (??Hxoor##YA?AV?$vec#N#0#ABV10#0#Z) referenced in function "void __cdecl testHook(void)" (?testHook##YAXXZ) main.obj
Update:
The following is now directly above the class definition. I continue to get the same linker error, as described above.
template<typename T>
class vec;
template<typename T>
vec<T> operator + (const vec<T>&, const vec<T>&);
Update 2: Solution.
The above update is incorrect. sbi's solution did work, I just failed to template the operator as follows.
template<typename T>
vec<T> operator +<T> (const vec<T>&, const vec<T>&);
sbi, and david were discussing why I was using friends in the first place. Initially I was using them, because you can not pass two parameters to an overloaded binary operator such as +, and immediate sought after friends as the solution. As it turns out, you can still use the binary operator quite easily with a single parameter. Here is the final solution.
// ...
template<typename T>
class vec{
public:
const vec<T> operator + (const vec<T>&, const vec<T>&)const;
// ...
}; // Vec.
template<typename T>
const vec<T> vec<T>::operator + (const vec<T>& v)const{
matrix<T> product = *this;
vec(product += v);
} // Addition.
Also, for anyone else reading this, its worth while to check out sbi's notes at the bottom of his answer. There are some things I've been doing that are superfluous.
Thanks for the help everyone. Happy coding.
In order to befriend a template, I think you'll need to declare that template before the class definition in which you want to befriend it. However, for this declaration to compile, you'll need to forward-declare the class template. So this should work:
template<typename T>
class vec;
template<typename T>
vec<T> operator + (vec<T>, const vec<T>&);
template<typename T>
class vec{
public:
friend vec<T> operator +<T> (vec<T>, const vec<T>&);
// ...
This befriends a specific instance of the operator+() function template, namely operator+<T>. (You can also befriend all instances of a template:
// no forward declarations necessary
template<typename T>
class some_class {
template<typename U>
friend void f(vec<U>&);
// ...
};
However, that's less often useful than the other one.)
Edit: A comment by David got me thinking (should've done this from the beginning!) and that lead to the discovery that the friend declaration is unnecessary. Your operator+ is only using one public member function of vec (operator+=) and thus doesn't need to be a friend of the class. So the above would simplify to
template<typename T>
class vec{
public:
// ...
};
template<typename T>
vec<T> operator + (vec<T> a, const vec<T>& b){
a += b;
return a;
}
Here's a few more notes:
operator+() (which you nicely implemented on top of operator+=(), BTW) should take its left argument per copy.
Don't declare functions as inline, define them so.
Have operator+=() return a non-const reference, because everybody expects f(m1+=m2) to work even if f() takes its argument as a non-const reference.
Inside of a class template, in most places you can omit the template parameter list when refering to the class. So you can say vec& operator += (const vec&);. (You cannot do this outside of the template, though - for example, when defining that operator outside of the class.)
A std::vector's index type is spelled std::vector<blah>::size_type, not unsigned short.
The return type here:
inline friend vec<T> operator + (const vec<T>&, const vec<T>&);
Does not match here:
template<typename T>
vec<T>& operator + (const vec<T>& a, const vec<T>& b){
vec<T> product = a;
product += b;
return product;
} // Addition.