Search code examples
c++member-functionsnon-member-functions

How to write in-class function from non-class function c++?


I have merge function which is a non-class.

Merge.cpp

template <typename T>
vector<T> merge(vector<T> left, vector<T> right){
    vector<T> result;
    int left_current = 0, right_current = 0;
    while(left_current < left.size() && right_current < right.size()){
        if(left[left_current] <= right[right_current]){
            result.push_back(left[left_current]); 
            left_current++;
        }else{
            result.push_back(right[right_current]); 
            right_current++;
        }
    }
    while(left_current < left.size()){
        result.push_back(left[left_current]); 
        left_current++; 
    }
    while(right_current < right.size()){
        result.push_back(right[right_current]); 
        right_current++;    
    }
    return result;
}


template <typename T>
vector<T> merge_sort(vector<T> arr){
    vector<T> left, right, result;
    if(arr.size() <= 1)
        return arr;
    int middle = arr.size() / 2;

    for(int i=0;i<middle;i++){
        left.push_back(arr[i]);
    }
    for(int i=middle;i<arr.size();i++){
        right.push_back(arr[i]);
    }

    left = merge_sort(left);
    right = merge_sort(right);
    arr = merge(left,right);
    return arr;
}

Normally, I am calling merge in main like this way.

vector<int> sorted_vector=merge_sort(my_vector);

But, I want to call in main like this way.

my_vector.merge_sort()

For calling in second way, I taught I need a member function which takes no parameters and arguments of Sorter class. So, I implemented my member function like following.

Sorter.cpp

template<typename T>
void Sorter<T>::merge_sort(){

    vector<int> sorted_vector = merge_sort(my_vector_2);

}

I made a research and I found this is about helper functions but I could not figure it out.Is my approach is correct ?


Solution

  • So I'm going to spout some platitudes.

    • Functions that are pure -- that take explicit input and return explicit output -- are easier to reason about.

    • Be lazy, do less work.

    Methods are, in general, impure; they operate on the object they are attached to, taking and returning its entire state implicitly. So if the function itself isn't a mess, state-wise, try to keep it as a pure function.

    On the other hand, having a function attached to an object is nice for the purpose of code-completion; by mentioning the noun (the object) first, brainless code-completion code can find your method and its signature easier. Meanwhile, free functions are this huge pile of verbs that is harder for code-completion tools to work with.


    Next, this code has a small issue you'll want to clean up:

    template <typename T>
    vector<T> merge(vector<T> left, vector<T> right){
    

    tweak this to:

    template <typename T>
    vector<T> merge(vector<T> const& left, vector<T> const& right){
    

    or even better, get ahold of span objects for left/right.


    For your method:

    template<typename T>
    void Sorter<T>::merge_sort();
    

    now, other than as an exercise, having a stateful object that is a "Sorter" is pretty ridiculous.

    I assume it looks something like this:

    template<typename T>
    class Sorter {
    public:
      std::vector<T> m_data;
      void merge_sort();
    };
    

    (the m_ part is just a reminder that this is a member).

    In this case, you'd write merge_sort like this:

    template<typename T>
    void Sorter::merge_sort() {
      m_data = ::merge_sort(m_data);
    }
    

    and done.

    (if merge_sort is in a namespace, say my_code, replace :: with my_code::).

    The annoying part is that merge_sort the method and merge_sort the function have the same name. By default, the member blocks finding the function, because of name lookup rules. The :: or my_code:: tells the compiler which merge_sort you are talking about.