operator overloading in global and element functions - c++

I'm new to cC++. I hope the code snippet explains well enough what I'm trying to achieve. I want a global and a element function for overloading of the < operator. In the element function the return type is bool and in the global function it is the respective type. Is this code possible to realize? (Not working right now?)
class Foo{
//...
//element function:
bool operator<(const Foo& otherFoo){//implementation}
}
//global function:
Foo& operator<(const Foo& foo1, const Foo& f2)
{
if (f1.operator<(f2))
return f1;
else;
return f2;
}

Is this code possible to realize?
Yes. But you really, really, really should not do it! operator< has a very concise meaning: Is the left hand side "less" (for some definition of "less") than the right hand side?
Returning the object which is actually "less" is also a reasonable function, but it should be named accordingly! Call it lesser_of or something like that.
Not working right now?
You did not include any useful error description in your question, but I highly suspect that the issue here is const correctness. You're accepting a reference to a const qualified Foo and try to call its member function operator< which is not const qualified. The simple fix: Add a const to the member function:
// member function: vvvvv
bool operator<(const Foo& otherFoo) const {
// implementation ^^^^^
}
The supposed free (= non-member) function (which should really be called with a reasonable name, I chose lesser_of) can be implemented for all types with a corresponding member function, using a template:
template<typename L, typename R>
typename std::common_type<L,R>::type lesser_of(L&& left, R&& right) {
using std::forward;
// Could also use operator<(forward<L>(left), forward<R>(right)), but
// this breaks when there's both a member function and a free
// function available.
if (left.operator<(forward<R>(right))) {
return forward<L>(left);
} else {
return forward<R>(right);
}
}
Note that I have no idea whether the forwarding makes any sense, nor am I sure if this could lead to dangling references.
Going a bit further, there's one kind of usage that I would consider "only just ok" if you really insist on returning "more" than a bool from operator<: In Common Lisp this is called "generalized boolean", and basically means that anything except a special nil value is considered to be "truthy". You could "port" that to C++ and use std::optional (C++17!) to convey that meaning:
template<typename L, typename R>
std::experimental::optional<L> operator<(L&& left, R&& right) {
if (left.operator<(std::forward<R>(right))) {
return std::forward<L>(left);
} else {
return std::experimental::nullopt_t{};
}
}
This returns the left operand wrapped in a std::optional if indeed it is "less" than the right. The result can be checked for in e.g. an if (or similar "special context") because it has a (explicit) conversion member function to bool. Thus returning std::optional instead of bool won't break code that uses the comparison only where contextual conversions can be applied. The returned value can be access by dereferencing or for example the value member function.
Of course this does not allow code like Foo c = a < b;, but you could instead use Foo c = (a < b).value_or(b);.

Related

How to create a type wrapper with reference-like semantics?

I want an object which can wrap a value symantic type and pretend that it is a reference.
Something like this:
int a = 20;
std::list<Wrap<int>> l1;
l1.push_back(a);
std::list<Wrap<int>> l2;
l2.push_back(a);
l2.front() = 10;
cout << l1.front() << endl; // output should be 10
While writing this question it occured to me that a shared_ptr might be what I want. However I am not sure if a pointer symantic object is what I am looking for. Perhaps there is no alternative in the standard library?
std::shared_ptr<int> a = std::make_shared(10);
std::list<std::shared_ptr<int>> l1;
l1.push_back(a);
std::list<std::shared_ptr<int>> l2;
l2.push_back(a);
*(l2.front()) = 20; // not exactly what I wanted to write
cout << *l1.front() << endl; // prints 10
I found std::reference_wrapper but this appears to be the opposite of what I want. It appears to permit a reference type to be used like a value type which is the reverse of what I wanted.
Any thoughts?
Proxy Object
As far as I know, there isn’t such a wrapper in the Standard Library. Fortunately though, you can implement one yourself rather easily.
How to start? Well, we’d like our Wrap<T> to be possibly indistinguishable from a T&. To achieve this, we can implement it as a proxy object. So, we’ll be making a class template storing a T& ref and implement operations one by one:
template<typename T>
struct Wrap
{
private:
T& ref;
public:
// ???
};
Construction
Let’s start with constructors. If we want Wrap<T> to behave like a T& it should be constructible from the same things that T& is constructible. Well then, what is a reference x constructible from?
A non-const lvalue reference like T& x = ...; needs to be constructed from an lvalue of type T. This means that it can be constructed from:
an object of type T
an object of a type derived from T
a different lvalue reference to T
an object convertible to T&
a function call returning T&
A const lvalue reference like const T& x = ...; can also be constructed from a braced-initializer-list or materialized from a temporary, however if we wanted to implement that, then we’d need to actually store a T inside of our class. As such, let’s focus on a non-const reference.
First, let’s implement a constructor from T& which will cover all of the cases shown above:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
The constructor is constexpr and noexcept because it can be. It is not explicit because we want to be able to use Wrap as transparently as possible.
We need to remember though, that a reference needs to be initializable from a different reference. Because we want our type to behave just like a builtin reference, we need to be able to
initialize a Wrap from a T& (already implemented above)
initialize a Wrap from a different Wrap
initialize a T& from a Wrap
To meet these criteria, we’ll need to implement a conversion operator to T&. If Wrap<T> will be implicitly convertible to T&, then assigning it to a builtin reference will work.
Actually, this:
int x;
Wrap w = x;
Wrap w2 = w;
will also work (ie. w2 will be Wrap<int> rather than a Wrap<Wrap<int>>) because the conversion operator takes precedence.
The implementation of the conversion operator looks like this:
constexpr operator T&() const noexcept
{
return ref;
}
Note that it is constexpr, noexcept and const, but not explicit (just like the constructor).
Miscelaneous operations
Now that we can construct our custom reference wrapper, we’d also like to be able to use it. The natural question is “what can you do with a reference”? Well, builtin references aren’t objects but merely aliases to existing objects. This means that taking the address of the reference actually returns the address of the referent or that you can access members through a reference.
All these things could be implemented, for example by overloading the arrow operator operator-> or the address-of operator operator&. For simplicity though, I will omit implementing these operations and focus only on the most important one: assignment.
Assignment
Firstly, we’d like to be able to assign a Wrap<T> to a T& or a T or basically anything that can be assigned a T. Fortunately, we already got that covered by having implemented the conversion operator.
Now we only need to implement assignment to Wrap<T>. We could be tempted to just write the operator like this:
constexpr T& operator=(const T& t)
{
ref = t;
return ref;
}
constexpr T& operator=(T&& t) noexcept
{
ref = std::move(t);
return ref;
}
Seems fine, right? We have a copy assignment operator and a noexcept move assignment operator. We return a reference as per custom.
Well, the problem is that this implementation is incomplete. The thing is that we don’t check
is T copy-assignable
if it is, then is it nothrow-copy-assignable
is T move-assignable
if it is, then is it nothrow-move-assignable
what is the return type of T’s assignment operator (it could be the customary T&, but it could also theoretically be anything else, like void)
does T have any other assignment operators
This is a lot of cases to cover. Fortunately, we can solve this all by making our assignment operator a template.
Let’s say that the operator will take an object of arbitrary type U as its argument. This will cover both the copy and move assignment operators and any other potential assignment operators. Then, let’s say that the return type of the function will be auto, to let the compiler deduce it. This gives us the following implementation:
template <typename U>
constexpr auto operator=(U u)
{
return (ref = u);
}
Unfortunately though, this implementation is still not complete.
We don’t know if the assignment is noexcept
We don’t distinguish copy assignment and move assignemnt and could potentially be making unnecessary copies.
Is the return type (auto) really correct?
To solve the first issue we can use a conditional noexcept. To check if the assignment operator is noexcept we can either use the type trait std::is_nothrow_assignable_v or the noexcept operator. I think that using the noexcept operator is both shorter and less error-prone, so let’s use that:
template <typename U>
constexpr auto operator=(U u) noexcept(noexcept(ref = u))
{
return (ref = u);
}
To solve the issue of distinguishing copies and moves, instead of taking a U u, we can take a forwarding reference U&& u, to let the compiler deal with all of this. We also need to remember about using std::forward:
template <typename U>
constexpr auto operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return (ref = std::forward<U>(u));
}
There is a bit of code duplication, but, unfortunately, it is inevitable, unless we’d use std::is_nothrow_assignable_v instead.
Finally, is the return type correct? Well, no. Because C++ is C++, parentheses around the returned value actually change its type (ie. return(x); is different from return x;). To return the correct type, we’ll actually also need to apply perfect forwarding to the returned type as well. We can do this by either using a trailing return type or a decltype(auto) return type. I will use decltype(auto) as it’s shorter and avoids duplicating the function body yet again:
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
Conclusion
Now, finally, we have a complete implementation. To sum things up, here it is all together (godbolt):
template<typename T>
struct Wrap
{
private:
T& ref;
public:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
constexpr operator T&() const noexcept
{
return ref;
}
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
};
That was quite a bit of C++ type theory to get through to write these 21 lines. Oh, by the way, did I mention value categories...

const function and references

If you notice in the following functions they both have the same for loop that searches for a integer location. Pop() compiles but I get an error for top() having to do with the const qualifiers. The heap class inherits from eecs281heap which stores a functor Comp compare where Comp is the typename. The instructor told us the only way to access the functor is through this->() so i'm just lookin for some guidance here. Thanks
error: passing ‘const larger’ as ‘this’ argument of ‘bool larger::operator()(int, int)’ discards qualifiers
This happens after running the following in int main. Through testing I already know the constructor works properly.
vector <int> data={10,2,13};
poorman_heap<int,larger> y(data.begin(),data.end());
template<typename TYPE, typename COMP>
void poorman_heap<TYPE, COMP>::pop() {
int location=0;
for(int i=1;i<data.size();i++){
if(this->compare(data.at(i),data.at(location))){
location=i;
}
}
data.erase(data.begin()+location);
return;
}
template<typename TYPE, typename COMP>
const TYPE& poorman_heap<TYPE, COMP>::top() const {
int location=0;
for(int i=1;i<data.size();i++){
if(this->compare(data.at(i),data.at(location))){
location=i;
}
}
return data.at(location);
}
P.S. greater is
struct greater{
bool operator()(int x,int y){
return x>y;
}
}
Make the call operator of greater a const operator:
struct greater
{
bool operator()(int x,int y) const
{
return x>y;
}
}
The same applies to whatever this->compare resolves to. It needs to be const.
It doesn't make much sense for a comparator to be non-const.
It looks like the problem is that the compare member has operator() declared as a non-const function. Since it sounds like you don't have the ability to change that, you might be able to get the behavior that you want by declaring it as a mutable member in poorman_heap.
The mutable keyword lets you distinguish between an object being "physically const" (meaning the actual bytes don't change and being "logically const" (meaning the bytes might change but the value of the object isn't different in a fundamental sense). Basically it means that something "doesn't count" for the purposes of const-ness. The classic example in my mind is lazy initialization - you want to declare the get_value() function on a class const, but you also don't want to waste time computing the value if no one uses it, so you declare the value mutable and now you're allowed to calculate it and assign to it inside get_value() even though it is a const member function.

What's the difference between a Predicate and a Functor?

I just read somebody call a class with a constructor and an operator() a predicate:
// Example
class Foo {
public:
Foo(Bar);
bool operator()(Baz);
private:
Bar bar;
};
However, I haven't heard the word predicate being used in this context before. I would call such a thing a functor. For me, a predicate would be something from the domain of formal logic.
This raises the following questions:
Is this a common word for something like Foo?
Are both terms used interchangeably, or do they mean slightly different things?
Or
Does the return type (bool versus something else) have something to do with it?
What about the operator() being const?
Functor is a term that refers to an entity that supports operator () in expressions (with zero or more parameters), i.e. something that syntactically behaves as a function. Functor is not necessarily an object of some class with overloaded operator (). Ordinary function names are functors as well. Although in some contexts you can see the term "functor" used in a more narrow and exclusive sense: just class objects, but not ordinary functions.
A predicate is a specific kind of functor: a functor that evaluates to a boolean value. It is not necessarily a value of bool type, but rather a value of any type with "boolean" semantics. The type should be implicitly convertible to bool though.
The shown class is a functor that implements a predicate.
A predicate is a boolean function.
About the operator() being non-const here: it should ideally be const, yes.
A predicate is a special kind of function object. See this excellent column by Nicolai Josuttis. To quote:
A function object that returns a Boolean value is a predicate. That's
what almost all tutorials, books, and manuals write about predicates
of the STL. This, however, is not the whole story.
However, there is an additional requirement that is unfortunately not
mentioned in any manual or in the C++ Standard: A predicate should
always return the same result for the same value.
Or, in the language of C++: You should declare operator() as a
constant member function (and not play games with mutable or casts).
For the same reason, a copy of a predicate should have the same state
as the original.
The reason is that the STL algorithms will copy function objects around, and the copying should not affect the outcome of applying the function objects.
template<typename Arg0>
struct UnaryPredicate
:
public std::function<bool(Arg0 const&)>
{
bool operator()(Arg0 const& a0) const
{
return // your code here
}
};
template<typename Arg0, typename Arg1>
struct BinaryPredicate
:
public std::function<bool(Arg0 const&, Arg1 const&)>
{
bool operator()(Arg const& a0, Arg const& a1) const
{
return // your code here
}
};
As has been said, a predicate is just a user supplied directive to analyze something to a boolean state. So you can have the same two things doing the same thing...
struct is_odd
{
is_odd() : count(0);
bool operartor () (int i) const { ++count; return (i % 2) == 1; }
private
int count;
}
And...
bool isOdd(int i) { return (i % 2) == 1; }
So, what is so special about the functor? It maintains state if you want it to! That means that while these two lines of code do the same thing (assume v is a vector, with values 0 - 9)...
for_each(v.begin(), v.end(), isOdd); //using C-style function pointer
And...
is_odd fn = for_each(v.begin(), v.end(), is_odd); //using functor
Only with the second use case can you then call...
int calls = fn.count;
That is because for_each (as well as other STL algorithm functions) returns the functor it used at the end, so now the final state can be queried.
One other cool thing to note is that in the second case, we are using what is called an "anonymous" object.
From the MSDN:
Represents the method that defines a set of criteria and determines
whether the specified object meets those criteria.
http://msdn.microsoft.com/en-us/library/bfcke1bz.aspx

How do I compare two generic types in C++?

I need to determine whether an element is the same as the one I'm passing by reference.
In the function Belongs I need to compare equality between d is and an element of a stored in a dynamic list:
struct Nodo{ Dominio dominio; Rando rango; Nodo* next; };
typedef Nodo* ptrNodo;
ptrNodo pri;
template<class Dominio, class Rango>
bool DicListas<Dominio,Rango>::Belongs(const Dominio &d)
{
bool retorno = false;
if(!EsVacia())
{
ptrNodo aux=pri;
while(aux!=NULL)
{
if(aux->dominio==d)//-------> THIS CLASS DOESN'T KNOW HOW TO COMPARE THE TYPE DOMINIO.
{
retorno = aux->isDef;
}
aux = aux->sig;
}
}
return retorno;
}
Whatever type argument you provide for the type parameter Dominio, you've to overload operator== for that type.
Suppose, you write this:
DicListas<A,B> obj;
obj.Belongs(A());
then you've to overload operator== for the type A as:
class A
{
public:
bool operator == (const A &a) const
{
//compare this and a.. and return true or false
}
};
Also note that it should be public if it's a member function, and better make it const function as well, so that you can compare const objects of type A.
Instead of making it member function, you can make operator== a non-member function as well:
bool operator == (const A &left, const A & right)
{
//compare left and right.. and return true or false
}
I would prefer the latter.
It reduces to defining an overload of operator== for the user-defined type:
bool operator==(const WhateverType &a, const WhateverType &b)
{
return whatever;
}
or maybe as a member of WhateverType.
If you want to compare something about two, possibly distinct, types, you probably want to look at either Boost type traits or the versions of type traits that made it into TR1 and C++11 (if you're using a compiler that supports either TR1 or C++11).
However, that doesn't seem to be the case that you're running into. In your case, you know that the two objects are of the same type. In C++, you will get compiler errors if a class you pass as a type parameter to a template does not support all the methods or operators that the template needs. That's what you're running into. That's also the problem that concepts are meant to solve (well, concepts are meant to advertise "if you want to use your type with this template, then your type must support ..."). But, unfortunately we didn't get concepts in C++11, so the requirements are implicit. In your case, as already mentioned, you simply need to make sure that whatever class you pass in as Dominio supports operator==.
You may also want to look at Boost concept check to advertise that whatever type is passed in as Dominio must support operator==.

What's the meaning of this C++ struct?

I got a simple C++ struct as follows:
// Functor for peak to decreasing intensity sorting
struct cmp_decr_int2
{
bool operator() (peak2 a, peak2 b)
{
return a.int2 > b.int2;
}
};
is there an overload of the operator in this sample?
Yes. operator() is called the "function call" operator, and allows an object to be usable as if it were a function. Such a class is called a "functor".
A common pattern is to make functors that compare two things for equality or relations, for use in anything requiring a comparison predicate. (This one could be usable in an std::map, for example. It would have a member likecmp_decr_int2 compare; and then it could compare the relation between two things with: if (compare(x, y)) /* x is less than y, by some metric */)
This particular struct orders two peak2's by comparing their int2 members. It could be better written as:
struct cmp_decr_int2
{
// note const! vvvvv
bool operator() (peak2 a, peak2 b) const
{
return a.int2 > b.int2;
}
};
The function should be const because it does not need to change any members (there are none to change.) const-correctness is important.*
In many cases these functors are used in contexts where the arguments themselves are const, so you should either take the arguments by value as in the example or by constant reference.
You should prefer to pass types by const-reference over by-value, except when that type is fundamental (float, unsigned int, double, etc.) or smaller than a void*. In most cases, then, you will pass by const-reference:
struct cmp_decr_int2
{
// note const&: vvvvv v vvvvv v vvvvv
bool operator() (const peak2 & a, const peak2 & b) const
{
return a.int2 > b.int2;
}
};
*If this were used as a predicate in a std::map, for example, without const the map wouldn't be able to compare two things while within a const function.
Structs in C++ are just classes with a default accessor of public instead of private. So yes, that would have a function overload.
in c++ a struct is in every way like a class, except that the default parameter access is public: rather than private:. It is a common practice to use struct instead of class when the scope of the defined type's use is very narrow, such as in the example of a simple functor.
What this example does is emulate the appearance of a function pointer without the fragility of possibly being null.
The operator() member here overloads function calling. when you try to do something like:
cmp_decr_int2 foo;
foo(peek2(), peek2());
that overload member gets called.
#include <iostream>
using namespace std;
struct cmp_decr_int2
{
bool operator() (int a, int b)
{
return a > b;
}
bool operator() (int i)
{
return i > 0;
}
};
int main()
{
cmp_decr_int2 a;
cout << a(1, 2) << endl;
cout << a(1) << endl;
}
Yep, sure can overload the function! This worked perfectly for me.
$13.5.4 states-
operator() shall be a non-static member function with an arbitrary number of parameters. It can have default arguments. It implements the function call syntax postfix-expression ( expression-listopt ) where the postfix-expression evaluates to a class object and the possibly empty expression-list matches the parameter list of an operator() member function of the class. Thus, a call x(arg1,...) is interpreted as x.operator()(arg1, ...) for a class object x of type T if T::operator()(T1, T2, T3) exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3.3).
Therefore, the struct 'cmp_decr_int2' has definitely overloaded operator().
Note that this is also the only operator in C++ that can take variable number of arguments.