0

I encountered the problem during an interview. I had to create a multimap which had as keys objects with one private member(a string, the name of the object) and mapped value ints(not relevant). There was one restriction imposed by the person leading the interview: there should be not get or set functions associated to the member string of the object. After some processing of the multimap with STL functions(like removing some elements), the following was requested: to extract the name of the key objects into a vector while removing any duplicates. I do not know how to extract the name of the key objects without having a get function(I could remove the duplicates once the extraction is performed). The person leading the interview brought into discussion functors and possibility to use a functor which could be a friend of the Object class. Please let me know if you have any idea how this could be solved! I provide bellow a simplified version of the code creating the multimap.

class Object
{
    std::string m_name; /* no set or get function allowed */
public:
    Object(std::string name): m_name(name) {}
    friend bool operator< (const Object& o1, const Object& o2)
    {
        return o1.m_name.compare(o2.m_name) < 0;
    }
};
void testMap()
{
    std::multimap<Object, int> m1;
    m1.insert(std::make_pair(Object("abc"), 1));
    m1.insert(std::make_pair(Object("qwerty"), 2));
    m1.insert(std::make_pair(Object("def"), 3));
    m1.insert(std::make_pair(Object("qwerty"), 4))
    /* extract Objects names in a vector while removing duplicates without adding a get m_name function */
}

Please let me know if you have any idea how this could be solved! I do not know how to access m_name which is private without a get function...

DrRzvn
  • 23
  • 3
  • 1
    If you have no way to get the name, there's no way to get the name. It's that simple. – Some programmer dude Oct 26 '22 at 16:26
  • @Someprogrammerdude to insert a name into a set you need to have a name first. If you have a name, you don't need a set, ust insert it to an array. But you have a multiset. Nothing else. – n. m. could be an AI Oct 26 '22 at 16:27
  • Unless you can modify the class you can't add friendship, but that that point adding a getter and setter seems more appropriate to me. There is a [trick with templates](https://stackoverflow.com/questions/12993219/access-private-member-using-template-trick) that you can use to access the private member of a class but being asked about that in an interview seems unreasonable to me. – NathanOliver Oct 26 '22 at 16:29
  • The question could be formulated much more simply: You have a class with a private member variable. How do you get access to this private member variable without modifying the class (i.e. you can't add a "getter" function)? The map (or set?) and the vector are just red herrings. – Some programmer dude Oct 26 '22 at 16:29
  • I received as hint that I could use a friend class which could also be a functor. The solution was requested also involve some STL function usage. Not sure if strictly at this point, as the problem also had also other points which were solved with STL. – DrRzvn Oct 26 '22 at 16:35
  • 1
    My answer would have been : If I would even be able to do that, that would break the original design (encapsulation) and would cause havoc during the long maintenance lifetime of the product. The internal desing of the original class should be refactorable as long as its interface (public methods) do not change (syntactically and semantically). So I would not even try to "solve" this. I would be delighted if one of our candidates would give such a reply. A job is not always about blindly following orders ;) – Pepijn Kramer Oct 26 '22 at 16:50
  • 1
    Maintaining software is already difficult enough with the public parts of the classes exposed. https://www.hyrumslaw.com/. Would have been fun to quote that if your interview was at google :) – Pepijn Kramer Oct 26 '22 at 16:53

2 Answers2

1

Not a nice solution, but using the fact that m1.begin() will always point to the alphabeticly first element we can decide if a given string would be the first in it, by inserting it to the map, and erasing it after the check. So we can start a binary-search caracter by character for the first string. Using this we can extract all keys from the map (by removing the already ones we find). I know this solution is a bit unortodox, and making a getter (or a friend function/class what is effectively a getter) is way better, but this can be done without modifying the class.

bool is_first(std::string s,std::multimap<Object,int>& m){
    auto it=m.insert(std::make_pair(Object(s), -1));
    bool res=it==m.begin();
    m.erase(it);
    return res;
}
bool eq(const Object&a,const Object& b){
    return (!(a<b)) && (!(b<a));
}
std::string get_first(std::multimap<Object,int> m){
    int len=0;
    std::string res;
    while (1){
        char mn=-128,mx=127,mid;
        res+=mn;
        while(mn+1!=mx){
            mid=(mn+(int)mx)/2;
            res[len]=mid;
            if (is_first(res,m)){
                mn=mid;
            }else{
                mx=mid;
                if (eq(m.begin()->first,Object(res)))
                    return res;
            }
        }
        res[len]=mn;
        ++len;
    }
}

void testMap()
{
    std::multimap<Object, int> m1;
    m1.insert(std::make_pair(Object("abc"), 1));
    m1.insert(std::make_pair(Object("abc"), 1));
    m1.insert(std::make_pair(Object("qwerty"), 2));
    m1.insert(std::make_pair(Object("def"), 3));
    m1.insert(std::make_pair(Object("qwerty"), 4));
    while (!m1.empty()){
        std::string s=get_first(m1);
        std::cout<<s<<" ";
        m1.erase(s);
    }
}

The motto for this solution: "If it stupid but it works, then it isn't stupid"

Botond Horváth
  • 929
  • 2
  • 15
  • Thank you very much for your unusual solution! Quite creative! But I still wonder if this is what the author of the problem was thinking about... – DrRzvn Oct 26 '22 at 18:04
  • I think not, as I didn't use any functors, or friends what he mentioned. But what I don't get is why he bringed thoose up. I mean you can define friends, and getters in the same place... But even if the author didn't think to it, it is a correct answer to his question. (And it removes duplicates by design) – Botond Horváth Oct 26 '22 at 18:16
0

If the interviewer mentioned "to use a functor which could be a friend of the Object class," this implies that you are allowed to modify class Object by adding a friend declaration. In that case, you can simply add a friend function (I don't see why a Functor would be better) like

class Object
{
    std::string m_name; /* no set or get function allowed */
public:
    Object(std::string name): m_name(name) {}
    friend bool operator< (const Object& o1, const Object& o2)
    {
        return o1.m_name.compare(o2.m_name) < 0;
    }
    friend std::string name(const Object& o)
    {
        return o.m_name;
    }
};

I cannot be sure, though, that the interviewer had this in mind; as @NathanOliver mentioned, there is a template trick to access a private member, but I cannot imagine that someone would ask that at an interview.