What is the meaning of the ==<> operator? - c++

Looking into some code of a colleague of mine, I came accross the following:
friend bool operator==<>(ValueIter<Type> const &rhs, ValueIter<Type> const &lhs);
It is declared in a template class:
template<typename Type>
class ValueIter: public std::iterator<std::bidirectional_iterator_tag, Type>
Can someone tell me what the ==<> symbol indicates? I expect it has something to with the != operator.

It looks like two, the operator== that is a full template instantiation or specialisation <>.
I've seen only a few like this in the wild though.
Given the friend, the class is probably befriending the template operator.
If you are getting linker errors with it, see this answer for why.

Your question is incomplete.
Presumably, in some context within the code you are examining, there is a templated operator==() function.
Then within some class, a particular specialisation of that templated operator==() is being declared as a friend.
Without context that you haven't given (i.e. of the preceding template definition, or of the enclosing class definition) it is not possible to give a more specific answer. There are too many possibilities for what the template or relevant specialisations are.

With
template <typename T> class ValueIter;
template <typename T>
bool operator==(ValueIter<T> const &rhs, ValueIter<T> const &lhs);
Inside template <typename T> class ValueIter
friend bool operator==(ValueIter const &rhs, ValueIter const &lhs);
and friend bool operator==(ValueIter<T> const &rhs, ValueIter<T> const &lhs);
add friendship to a non template operator.
friend bool operator==<>(ValueIter const &rhs, ValueIter const &lhs);,
friend bool operator==<>(ValueIter<T> const &rhs, ValueIter<T> const
friend bool operator==<T>(ValueIter const &rhs, ValueIter const &lhs);,
friend bool operator==<T>(ValueIter<T> const &rhs, ValueIter<T> const
add friendship to the template operator (just for the type with match T)
template <typename U> friend bool operator==(ValueIter<U> const &rhs, ValueIter<U> const &lhs); add friendship to the template operator (for any type U (which may differ of T))
==<> is used in the second point and is really == <>.

Related

Unnresolved externals [duplicate]

I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.
I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.
template <typename T, unsigned int TN>
class NVector {
friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
// code goes here
return o;
}
};
Alternatively you can opt for other options:
declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
declare a particular instantiation of that template as a friend (more cumbersome to write) or
avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.
The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:
template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};

Template class with implicit conversion and operator overload but not inline

Based on the answer in Implicit conversion when overloading operators for template classes I was able to write the following code that works perfectly fine (simplified example):
namespace my_library {
template <typename T>
struct Number {
T n;
inline Number(T n) : n(n) { }
friend Number<T> operator+(const Number<T> &a, const Number<T> &b) {
return Number<T>(a.n + b.n);
}
};
}
int main() {
return (int) (4 + my_library::Number<double>(3)).n; // returns 7
}
All I want to do is make it so that operator+ is not inlined within the definition of Number (but stays in the header file) while everything still works the same way - see the expression in the main function. Note that it requires that the integer 4 gets implicitly converted to double and then to Number<double>. I followed a comment linking to Binary operator overloading on a templated class but that solution did not work - the overloaded operator is no longer matched. Is there any way to make this work and have the body of the operator outside the struct definition? (Without complicating the operator interface or adding more overloads - in those cases I'd rather just keep it inlined.)
You can do it like this:
template <typename T>
struct Number {
// ...
template <class U>
friend Number<U> operator+(const Number<U> &a, const Number<U> &b);
};
template <typename U>
Number<U> operator+(const Number<U> &a, const Number<U> &b) {
return Number<U>(a.n + b.n);
}
In this example, operator+ will be a friend of all Number specializations even when the types don't match. This might be a broader friendship than you intended, but is the simplest way to achieve your objective of moving the definition of operator+ outside the definition of Number. Note that when a friend is not defined inline, you lose the benefit of having it as a "hidden friend". (A hidden friend can only be found via argument-dependent lookup, which means that the compiler will typically not have to consider it as a candidate function in most cases where it is not intended to be used.)
If you want each specialization of operator+ to only be a friend of one particular Number specialization where the types match, it is more complicated. You have to forward-declare the operator+ template in order to prevent the friend declaration from declaring a non-template function, and you also have to forward-declare Number so that it can be used in the operator+ forward declaration:
template <typename T> struct Number;
template <typename T>
Number<T> operator+(const Number<T>&, const Number<T>&);
template <typename T>
struct Number {
// ...
friend Number<T> operator+<>(const Number<T>&, const Number<T>&);
};
template <typename T>
Number<T> operator+(const Number<T> &a, const Number<T> &b) {
return Number<T>(a.n + b.n);
}

friend operator in nested class of templated class

I want to add a iterator class type for my vector class,and I declare some compare operator as friend function of iterator class.but it didnt complie correctly,I did forward declaration.
template<class object>class vector;
template<class object>
bool operator<(typename vector<object>::const_iterator& lhs, typename vector<object>::const_iterator& rhs);
template<class object>class vector {
protected:
//some member
public:
class const_iterator {
friend bool operator< <>(const_iterator& lhs, const_iterator& rhs);
friend bool operator> <>(const_iterator& lhs, const_iterator& rhs);
//...
};
};
compiler said no matching overloaded function found,I use vs2019.I guess something wrong with forward declaration.
and another question is,I notice some people use this form when declare friend function inside class.
class myclass{
friend void foo<T>(T t);
//...
}
but when declare a operator as friend it's different
friend bool operator< <>(const myclass& lhs, const myclass& rhs);
I wonder what's the difference between these two.
please help me,thanks a lot.
In your forward declaration
template<class object>
bool operator<(typename vector<object>::const_iterator&,
typename vector<object>::const_iterator&);
const_iterator is in the non-deduced context, i.e. the compiler will not be able to deduce int for object in the following call:
vector<int>::const_iterator c1;
vector<int>::const_iterator c2;
c1 < c2;
I can suggest two solutions.
The simplest one: omit your forward declarations and provide a definition for operator< inside the body of const_iterator:
friend bool operator<(const_iterator& lhs, const_iterator& rhs) {
... return ... ;
}
If you can't define operator< inside const_iterator, use CRTP to turn a non-deduced context into a deduced one:
template<class derived>
struct const_iterator_crtp {};
template<class derived>
bool operator<(const_iterator_crtp<derived>&,
const_iterator_crtp<derived>&);
template<class object>
struct vector {
struct const_iterator : const_iterator_crtp<const_iterator> {
using base = const_iterator_crtp<const_iterator>;
friend bool operator< <>(base&, base&);
private:
int priv;
};
};
template<class derived>
bool operator<(const_iterator_crtp<derived>& lhs,
const_iterator_crtp<derived>& rhs)
{
auto& l = static_cast<derived&>(lhs); // these static_cast's are safe
auto& r = static_cast<derived&>(rhs);
return l.priv < r.priv;
}
Is the operator< a function template in the first solution? Why we don't need a <> after operator<?
It is not a template. You don't need <> in this definition.
You forward declare a template first. Without <>, a friend declaration introduces a non-template function. A non-template function, even if it has the same name as template one (non-template and template functions can overload!), should be defined somewhere. You'll get a link error without such a definition. To override the default behavior and to refer to the function template that was forward declared earlier, you add <>.

C++ : friend declaration ‘declares a non-template function

I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.
I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.
template <typename T, unsigned int TN>
class NVector {
friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
// code goes here
return o;
}
};
Alternatively you can opt for other options:
declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
declare a particular instantiation of that template as a friend (more cumbersome to write) or
avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.
The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:
template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};

template warnings and error help, (gcc)

I'm working on an container class template (for int,bool,strings etc), and I've been stuck with this error
cont.h:56: error: expected initializer before '&' token
for this section
template <typename T>
const Container & Container<T>::operator=(const Container<T> & rightCont){
what exactly have I done wrong there?.
Also not sure what this warning message means.
cont.h:13: warning: friend declaration `bool operator==(const Container<T>&, const Container<T>&)' declares a non-template function
cont.h:13: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
at this position
template <typename T>
class Container{
friend bool operator==(const Container<T> &rhs,const Container<T> &lhs);
public:
In the first case, you're saying just Container the first time instead of Container<T>.
In the second case, I think you need to repeat the template: while member functions of a template class are implicitly templated, friend functions aren't necessarily, so it's necessary to be more explicitly . I'm not sure what exact syntax you need for that purpose, but I think it is:
before the class, template<typename T> bool operator==( etc
in the class, bool operator==<>( etc
I think that's what the error message is trying to convey, though not super-clearly.
In the first case you've done things backwards. When you specify the return type, you have to include the template parameter list into the template identifier (Container<T>), but when you specify parameter type, you don't need to do it (just Container is enough)
template <typename T>
const Container<T> & Container<T>::operator=(const Container & rightCont){
...
You did it the other way around for some reason.
In the second case, when you declare operator == as a friend it simply warns you that that in this case operator == you are referring to is an ordinary function. It can't be a specialization of a template. I.e. for the class Container<int> the function
bool operator==(const Container<int> &rhs, const Container<int> &lhs) {
// ...
}
will be a friend. But specialization of function template
template <class U>
bool operator==(const Container<U> &rhs, const Container<U> &lhs) {
// ...
}
for U == int will not be a friend of Container<int>. If that's your intent, you are OK.
If you wanted to befriend a specific specialization of the above template, you'd have to say
template <typename T>
class Container {
friend bool operator==<T>(const Container<T> &rhs, const Container<T> &lhs);
...
If you wanted to befriend all specialization of the above template, you'd have to say
template <typename T>
class Container {
template <class U>
friend bool operator==(const Container<U> &rhs, const Container<U> &lhs);
...