Home > Back-end >  Is there anything like C default object method
Is there anything like C default object method

Time:09-17

I have the following templated merge sort program:

#include <iostream>
#include <vector>
#include <string>

// trying to create a default method call
class CInstance {
private:
    std::string str_;
public:
    CInstance(const std::string& str) : str_(str) {}
    bool const  operator>(const CInstance& that){  return (this->str_.size() > that.str_.size());}
};

template<class T>
class CObj {
private:
    T val;
public:
    CObj(const T n) : val(n) {}
    T Get() { return val; }
};

template<class T>
using vcobj = std::vector<CObj<T>>;

template<class T>
void display(vcobj<T>& v) {
    for (auto &i : v) {
        std::cout << i.Get() << " ";
    }
    std::cout << "\n";
}

template<class T>
vcobj<T> Merge(vcobj<T>& lv, vcobj<T>& rv) {
    vcobj<T> ret;
    
    auto lsize = lv.size();
    auto rsize = rv.size();
    unsigned int lpin = 0, 
                 rpin = 0;
                 
    while(lpin < lsize &&  rpin < rsize) {
        if(lv.at(lpin).Get() > rv.at(rpin).Get()) {
            ret.emplace_back(rv.at(rpin).Get());
            rpin  ;
        }
        else {
            ret.emplace_back(lv.at(lpin).Get());
            lpin  ;
        }
    }
    
    for (auto i=lpin; i<lsize; i  ) {
        ret.emplace_back(lv.at(i).Get());
    }
    
    for (auto i=rpin; i<rsize; i  ) {
        ret.emplace_back(rv.at(i).Get());
    }
    
    return ret;
}

template<class T>
vcobj<T> Sort(const vcobj<T>& v) {
    vcobj<T> ret;
    
    auto size = v.size();
    if(size == 0) {
        return ret;
    }
    if(size > 1) {
        
        auto mid = size / 2;
        
        vcobj<T> l(v.begin(), v.begin() mid);
        auto lv = Sort(l);
        
        vcobj<T> r(v.begin() mid, v.end());
        auto rv = Sort(r);
        
        ret = Merge(lv, rv);
        
    }
    else {
        ret = v;
    }
    
    return ret;
}

int main() {
    {
        vcobj<int> v = {4, 5, 2, 1, 9, 6, 10, 8, 15, 3, 7};
        display(v);
        auto sorted = Sort(v);
        display(sorted);
    }
    
    {
        vcobj<float> v = {0.01, 0.001, 0.002, 0.009, 0.010, 0.0003, 0.00001};
        display(v);
        auto sorted = Sort(v);
        display(sorted);
    }
    
    {
        vcobj<std::string> v = {{"pineapple"}, {"jackfruit"}, {"mango"}, {"apple"}, {"banana"}};
        display(v);
        auto sorted = Sort(v);
        display(sorted);
    }
    
    // causing problem
    {
        vcobj<CInstance> v = {{"pineapple"}, {"jackfruit"}, {"mango"}, {"apple"}, {"banana"}};
        display(v);
        auto sorted = Sort(v);
        display(sorted);
    }
    
    return 0;
}

In all of the above types, I can simply call the object and it extracts the data which looks like calling a default get() method. Is there a way to make objects of class CInstance trigger a methos, when used just alone.

example: I could do something like

CInstance obj;
std::cout << obj;

And that will call a default method in CInstance what every it may be.

CodePudding user response:

In this exact case, you define an operator<< method like so:

std::ostream & operator<<(std::ostream &stream, const CInstance &obj) {
    ... output obj however you want to the stream. For instance:
    stream << obj.getAge();
    return stream;
}

CodePudding user response:

As already mentioned in the other answer you can create your own operator<< function:

std::ostream & operator<<(std::ostream &stream, const CInstance &obj) {
    
    // stream <<  whatever you want to output

    return stream;
}

You could also define a conversion operator. But you should think twice before you use them. They can lead to problems that are not easy to debug, especially when explicit is omitted. You generally should not use those for logging/debugging purposes. If your type represents a string and you use it to allow an easy conversion to an std::string then it might be fine.

#include <iostream>
#include <string>

class CInstance {
    std::string str_ = "test";
public:
    explicit operator const std::string () const { return str_; }
};

int main() {
    CInstance obj;

    std::cout << (std::string)obj << std::endl;
    return 0;
}

If you can guarantee that the lifetime of the returned const char * is still valid after the call you could also do something like (but I would avoid that solution):

#include <iostream>
#include <string>

class CInstance {
    std::string str_ = "test";
public:
    operator const char *() const   { return str_.c_str(); }
};

int main() {
    CInstance t;

    std::cout << t << std::endl;
    return 0;
}

Personally, I would go with the first solution. But that really depends if you actually have a string representation of CInstance or if you want to display something for debugging purposes in a different format. I however would avoid the last non-explicit version with the const char * conversion operator.

  • Related