1

This the below program i have written for some test.

class tgsetmap
{
public:
std::map<std::string,std::string> tgsetlist;
void operator<<(const char *str1,const char *str2)
{
  tgsetlist.insert( std::map<std::string,std::string>::value_type(str1,str2));
}

};


int main()
{

tgsetmap obj;

obj<<("tgset10","mystring");

obj.tgsetlist.size();
}

This throws a compilation error:

"test.cc", line 10: Error: Illegal number of arguments for tgsetmap::operator<<(const char, const char*). "test.cc", line 22: Error: The operation "tgsetmap << const char*" is illegal. 2 Error(s) detected.*

Am i wrong some where?

Vijay
  • 65,327
  • 90
  • 227
  • 319

4 Answers4

4

You can't force operator<< to take two arguments on right-hand side. The following code:

obj<<("tgset10","mystring");

does not work as a function call with two arguments but instead just uses the , operator. But it's probably not what you are interested in.

If you need to pass two arguments to the << operator, you need to wrap them in some other (single) type. For example, you could use the standard std::pair, i.e. std::pair<const char*, const char*>.

But note that the operator<< should also return some reasonable type suitable for << chaining. That would probably be a tgsetmap& in your case. The following version should work fine:

#include <map>
#include <string>
#include <iostream>

class tgsetmap
{
public:
    typedef std::map<std::string, std::string> list_type;
    typedef list_type::value_type item_type;

    list_type tgsetlist;

    tgsetmap& operator<<(item_type item)
    {
        tgsetlist.insert(item);
        return *this;
    }
};

int main()
{
    tgsetmap obj;

    obj << tgsetmap::item_type("tgset10","mystring")
        << tgsetmap::item_type("tgset20","anotherstring");

    std::cout << obj.tgsetlist.size() << std::endl;
}

Note that I've added typedefs to not have to repeat the type names over and over again. I've also made operator<< return a tgsetmap& so that << could be chained (used like in the modified main() above). And finally, I've reused the std::map<...>::value_type to make it simpler but you could also use any other type of your own.


But I believe that you may prefer using a regular method instead. Something like:

void add(const char *str1, const char *str2)
{
    tgsetlist.insert( std::map<std::string, std::string>::value_type(str1, str2));
}

(inside the class declaration), and then:

obj.add("tgset10", "mystring");
Michał Górny
  • 18,713
  • 5
  • 53
  • 76
1

The operator<< inside of a class must be overloaded like this:

T T::operator <<(const T& b) const;

If you want to overload it with 2 arguments, you can do it outside of a class:

T operator <<(const T& a, const T& b);

My compiler, for example, gives a more detailed error message for the code you posted: enter image description here

If you are not sure about an operator overloading syntax, there is a wiki article about it.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
0

Yes. operator << is binary operator. not ternary. not forget about this pointer.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
0

As mentioned, the << is binary operator, so there is no way it can take more than two args(One should be this if you are declaring inside the class or a LHS if you are declaring outside the class). However you can accomplish the same functionality by doing obj<<"tgset10". <<"mystring";. But since << is a binary operator, you have to do some hack for this.

For this, I ve assigned a static variable op_count, where in I will determine if it is the value or the type. And another static variable temp_str to store the previous value across invocations.

class tgsetmap
{
    public:
    std::map<std::string,std::string> tgsetlist;

    static int op_count = 0;
    static const char *temp_str;
    tgsetmap& operator<<(const char *str)
    {
        op_count++;
        if (op_count%2 != 0) {
            temp_str = str;
        }
        else {
            tgsetlist.insert( std::map<std::string,std::string>::value_type(temp_str,str));
        }
        return this;
    }
};

So you can do

int main()
{
    tgsetmap obj;
    obj<<"tgset10"<<"mystring";
    obj.tgsetlist.size();
}

Or simply you can embed the value and type in the same string using some separator,

value:type = separator is :

value_type = separator is _.

Mohan
  • 1,850
  • 1
  • 19
  • 42