C++ How to overload the [] operator and make a function call - c++

Sorry. i do not know how to ask this question, so i will give a example.
Get the arg string from the command line
Example: MyProgram.exe -logs=yes -console=no
CmdLine CmdLine( ::GetCommandLine() ); // Get arg string.
When i have the arg string. i wish to look for "logs" ("yes") and "console" get its value
("no").
CmdLine.GetKey["logs"].GetValue(); // Get the value of "logs".
CmdLine.GetKey["console"].AsBool(); // Get the value of "console".
I have to overload the [] operator ( void operator[] ( const std::string & str ); )
GetKey["logs"]; // okay.
But i do not know how or if i can in C++ to do something like;
CmdLine.GetKey["console"].MyFunction(); // HOW to do this?
How can i tell "GetKey" to call "MyFunction(). (sorry for bad wording. but i do not know know
what this is called.
Thank you for patients and help and ideas.
EDIT:
Sorry for confusion!
CmdLine.GetKey["logs"].GetValue(); // Example!!!
I overload the [] so i can look up "logs" in a std::map, std::unordered_map (whatever).
When i find "logs" i wish for "GetKey["logs"]" to call "GetValue()" and return
the value.
I do know know what this is called when i do this;
Func().SomeFunc().SomeOtherFunc();
Because i want to do the example i tried to explain.

Lets dissect it step by step:
CmdLine.GetKey["logs"].GetValue();
// call method on some object
// call operator [] on GetKey
// GetKey is a member of CmdLine
As mentioned in a comment, GetKey is not a good name for a member. I suppose you don't really need it, but it was just your attempt to express that you are looking up the object on which you want to call GetValue() in CmdLine. I have to admit, I don't fully understand the example. Anyhow...
You can make operator[] return an object that has a member function that you can call:
#include <iostream>
struct foo {
std::string value;
void print() { std::cout << value; }
};
struct bar {
foo operator[](const std::string& x) {
return {x};
}
};
int main(int argc, char *argv[])
{
bar b;
b["hello world"].print();
}
Output:
hello world
For more on operator overloading read What are the basic rules and idioms for operator overloading?.

Related

I need to access the value within a const std::string& call in a function

I have a quick question regarding C++ and references to values. I have been asked to write a function that takes the input from const std::string& and use the input to perform some tasks. The issue is, I have no idea how to access the value. I know it is a pass-by reference value but I don't know how to access it within the function.
This is the code that I was given:
#include "rle.hpp"
std::string func_send(const std::string&)
{
//Implement !
return {};
}
std::string func_receive(const std::string&)
{
// Implement!
return {};
}
The code you were given makes no sense, at least there is no way to acces the parameter because it has no name. Moreover std::string str = std::string&; is invalid syntax, I don't know what it is supposed to mean. Give the parameter a name:
std::string func_send(const std::string& str)
// ^------------ !!!
{
std::string some_other_string = str;
return {}; // missing semi-colon
}

How to fix stack overflow on overloaded addition operator in c++

I'm trying to learn the concept of operator overloading in c++ but I have got stuck on a problem that I'm trying to solve using the operator+ where in the my main-function I add to userdefiend classes together.
The class constructor takes a string pointer as a parameter.
My understanding of the operatoroverloading concept is that you declare a function in a class, using the keyword operatorX, and replace X with the operator that you will like to overload. Like if i would like to overload the '-' operator I should write like this operator-. But when I debug my code it results in an Stack overflow and the program stops.
The class looks as follows:
class Hello{
public:
Hello(string str):pstr(&str){
}
//The overloaded function below
Hello operator+(Hello& h1){
Hello temp(*this);//creates a copy of the current Hello-object
temp = temp + h1;//adds the new value to the temporary object
return temp;
}
private:
string* pstr;//pointer to string-object
}
I know that i get the stack overflow in the overloaded function.
In the main method i have the following code:
void main(){
Hello h1("Hello ");
h1 + Hello("World");
}
I'm not shore that i've coded this in the right way but the result should be Hello World in the return object if i'm not mistaken.
How can I solve this so that I dont get the stack overflow when the code is running, and also how can I get the right return value?
in
Hello operator+(Hello& h1){
Hello temp(*this);//creates a copy of the current Hello-object
temp = temp + h1;//adds the new value to the temporary object
return temp;
}
the operator+ recursively calls itself, you have to really implement the addition
probably you wanted :
Hello operator+(const Hello& h1) {
Hello temp(*pstr + *(h1.pstr))
return temp;
}
Out of that, why do you have pstr as a pointer to a std::string rather than to have just a std::string str; ?
It is much more practical to have for instance :
class Hello{
public:
Hello(string s) : str(s) { }
Hello operator+(const Hello& h1){
Hello temp(str + h1.str);
return temp;
}
private:
string str;
};
Note if you really want to have string* pstr; your constructor
Hello(string str):pstr(&str){}
is wrong because you save the address of the parameter, you need to change it to for instance :
Hello(string str) : pstr(new string(str)) {}
and having a pointer you need to add the destructor to delete the string, and the copy constructor, the operator= etc look at rule_of_three
In operator overloading, the key concept to think is how would the behavior be if the type you were defining was a primitive type. For example, what would adding a pointer to string with another pointer to string look like.
As mentioned above, your definition is recursively calling operator+.
Here is an example that might be useful: https://www.geeksforgeeks.org/operator-overloading-c/

recursive application of operator->

It is said that the arrow operator is applied recursively. But when I try to execute the following code, it prints gibberish when it is supposed to print 4.
class dummy
{
public:
int *p;
int operator->()
{
return 4;
}
};
class screen
{
public:
dummy *p;
screen(dummy *pp): p(pp){}
dummy* operator->()
{
return p;
}
};
int main()
{
dummy *d = new dummy;
screen s(d);
cout<<s->p;
delete d;
}
What Stanley meant by “recursive” is just that the operator is applied to every returned object until the returned type is a pointer.
Which happens here on the first try: screen::operator -> returns a pointer. Thus this is the last call to an operator -> that the compiler attempts. It then resolves the right-hand sice of the operator (p) by looking up a member in the returned pointee type (dummy) with that name.
Essentially, whenever the compiler finds the syntax aᵢ->b in code, it essentially applies the following algorithm:
Is aᵢ of pointer type? If so, resolve member b of *aᵢ and call (*aᵢ).b.
Else, try to resolve aᵢ::operator ->
On success, set aᵢ₊₁ = aᵢ::operator ->(). Goto 1.
On failure, emit a compile error.
I’m hard-pressed to come up with a short, meaningful example where a chain of operator -> invocations even makes sense. Probably the only real use is when you write a smart pointer class.
However, the following toy example at least compiles and yields a number. But I wouldn’t advise actually writing such code. It breaks encapsulation and makes kittens cry.
#include <iostream>
struct size {
int width;
int height;
size() : width(640), height(480) { }
};
struct metrics {
size s;
size const* operator ->() const {
return &s;
}
};
struct screen {
metrics m;
metrics operator ->() const {
return m;
}
};
int main() {
screen s;
std::cout << s->width << "\n";
}
C++ Primer (5th edition) formulates it as follows on page 570:
The arrow operator never loses its fundamental meaning of member access. When we overload arrow, we change the object from which arrow fetches the specified member. We cannot change the fact that arrow fetches a member.
The deal is once screen::operator->() returns a pointer (dummy*) the recursion stops because built-in (default) -> in used on that pointer. If you want recursion you should return dummy or dummy& from screen::operator->()

Can we find the caller in a member function in C++?

I have a class, and let's called it class myClass
class myClass{
// some math operations
myClass get_difference(myClass &b)
{
print_operation(*this, b);
do_something else
return...
}
myClass get_sum(myClass &b)
// pseudocode
void print_operation(const myClass *a, const myClass &b)
{
if function == get_sum
print a << "plus" << b;
if function == get_difference
print a << "minus" << b;
}
// overload cout as well
};
Suppose I called the following
myClass anObject(1,2);
myClass anotherObject(3,4);
anObject.get_sum(anotherObject);
anObject.get_difference(anotherObject);
get_sum / get_difference will call print_operation, but I want to be able to determine the caller so a different output format is used.
Naive approach: Use switch-case
Add a new parameter called "id". Give each function (the caller) an id, and use switch-case statements in print_operation.
However, is there an alternative? A more elegant solution?
Thanks.
Have you considered adding a virtual const std::string& getFormatted() const in the caller?
If the format will be a function of both arguments to your operator, you would have to create some kind of table of combinations to look up your format.
If the format is only a function of the length of the printing of each argument (much simpler), you could use virtual size_t getFormatLength() const.
Note: print_operation() doesn't know anything about the caller, except that it has a getFormatted() function, yet the caller gets to format itself based on the value of op.
This is OOP/polymorphism at work.
As Andrew Marshall answered in his comment above, part of OOP/encapsulation is, you should not know anything about the implementation of the caller.
Polymorphism, done right, should try to encapsulate the implementation details away from the caller.
class myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const = 0;
};
class A : public myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const
{
// switch on the value of op or the length of op, etc...
return std::string( "this, formatted according to class A specs and op" );
}
};
class B : public myClass
{
public:
virtual std::string getFormatted( const std::string& op ) const
{
// switch on the value of op or the length of op, etc...
return std::string( "this, formatted according to class B specs and op" );
}
};
void print_operation(const myClass &a, const myClass &b )
{
std::string op;
if ( function == get_sum ) {
op = "plus";
} else if ( function == get_difference ) {
op = "minus";
}
std::cout << a.getFormatted( op ) << op << b.getFormatted( op );
}
Cpp functions don't know who is the caller unless you hack the stack, which is, kind of, complicated. So, generally speaking, you have to pass the information(in function parameter, template parameter, data member..) to print_operation to tell it what operation to print.
So the answer is no more elegant solution.
I don't think the problem boils down to knowing who the caller is. It sounds like you really want to define different ways to format the data and there may be different desired formatters for different callers.
Taking a lesson from .NET, you might consider a design where you have a format string to define how to output the data such as in IFormattable.ToString. In that example, a format string is used to differentiate different output formats. In your case, you could define it with an integer, an enum, or whatever is appropriate.

Calling the function pointed by a Pointer-to-Member-Function from within a struct

I have a class Test with a peculiar data structure.
A member of class Test is a std::map where the key is a std::string and the mapped value is a struct defined as follows:
typedef struct {
void (Test::*f) (void) const;
} pmf_t;
Initialization of the map is OK. The problem is when I am trying to call the function pointed. I made up a toy example reproducing the problem. Here it is:
#include <iostream>
#include <map>
using namespace std;
class Test;
typedef void (Test::*F) (void) const;
typedef struct {
F f;
} pmf_t;
class Test
{
public:
Test () {
pmf_t pmf = {
&Test::Func
};
m["key"] = pmf;
}
void Func (void) const {
cout << "test" << endl;
}
void CallFunc (void) {
std::map<std::string, pmf_t>::iterator it = m.begin ();
((*it).second.*f) (); // offending line
}
std::map<std::string, pmf_t> m;
};
int main ()
{
Test t;
t.CallFunc ();
return 0;
}
Thanks in advance,
Jir
The name of the pmf_t type is f, so the first change is to remove the * to get second.f. That gives you a pointer-to-member value. To use a pointer-to-member, you need an instance. The only one you have available of the correct type is this, so use it with the ->* operator:
(this->*it->second.f)();
You need parentheses around the whole thing, or else the compiler thinks you're trying to call it->second.f() (which isn't allowed) and then applying the result to ->*.
The offending line is trying to call a member function without any object to call it on. If the intention is to call it for the this object, I believe the call should look like
( this->* ((*it).second.f) )();
Where this->* is the syntax for dereferencing a pointer-to-member for the current object. ((*it).second.f) is the pointer retrieved from the map, and () is the call operator for actually calling the function.
This is perhaps good as an exercise, but otherwise of limited use.
I think you might want to check out the C++ FAQ on this one. The syntax is apparently pretty tricky to get right (they actually recommend using a macro).
It might be too late for this question but, the seemingly complex synatax can be break down to two simple lines so it looks pretty clear:
void CallFunc (void)
{
pmf_t t = m["key"]; //1>get the data from key
(this->*t.f)(); //2>standard procedure to call pointer to member function
}
try this:
(this->*((*it).second.f)) ();