1

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 ?

  • 1
    `my_vector` is a `std::vector` ? You cannot add members to classes on the fly like that. Whats wrong with a free function? – 463035818_is_not_an_ai Oct 27 '20 at 13:43
  • its not clear why you think having a member would be better than free function. I suggest you to read this: https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197 Actually if possible free functions are prefered over members – 463035818_is_not_an_ai Oct 27 '20 at 13:46
  • You can't. `std::vector` is a templated type in the standard library, and it's not possible in C++ to add member functions to standard types. It is only possible to add member functions to your *own* `struct` or `class` types, where you have control over (i.e. can edit) the `struct` or `class` definition. And that has to be done in the whole program (having two different definitions in different source files gives undefined behaviour, except in specialised cases that differ from what you seek). Although `std::vector` is a templated class, you don't have such control. – Peter Oct 27 '20 at 13:53
  • I have been asked to write a member function as an assignment which takes no parameters and return values. Since the merge sort is a recursive function, I taught that I can call actual function that does the sorting job from the member function – ömer feyzullahoğlu Oct 27 '20 at 13:55
  • oh, certainly you can call a free function from a member function – quetzalcoatl Oct 27 '20 at 13:56
  • I see that you've got a class called `Sorter` - what is it? is it a vector-like thing that needs to be sorted? – quetzalcoatl Oct 27 '20 at 14:00
  • Sorter class has methods like insert, insertion_sort, get_size, print etc. Yes it has also vector that needs to be sorted. – ömer feyzullahoğlu Oct 27 '20 at 14:03
  • Alright, then if that's true, then you are going in a good direction, but in `Sorter::merge_sort` doing `vector sorted_vector = merge_sort(my_vector_2);` you have to ensure that `my_vector_2` contains data from the Sorter object, and later the returned `sorted vector` is what you wanted to get, but it's not yet written back to the Sorter object, so you need to take care of it too! – quetzalcoatl Oct 27 '20 at 14:04
  • I created my_vector_2 in the main also. – ömer feyzullahoğlu Oct 27 '20 at 14:07
  • 1
    @quetzalcoatl the second is from "teach" not "learn" – 463035818_is_not_an_ai Oct 27 '20 at 14:15
  • `I created my_vector_2 in the main also.` then it will not work. `main()` is another scope. The member function `Sorter::merge_sort` will not see `my_vector_2` variable. Since Sorter is a vector-like thing, or contains a vector with data, be sure to pass that data or that vector to the sorting function. – quetzalcoatl Oct 27 '20 at 14:15
  • @idclev463035818: yeah true, thanks, I wrote it with google-translate and it did not feel OK, but somehow I didn't re-check it. Comment removed. I have to be MOAR careful. Funny thing: I have the same teach-learn problem when learning japanese.. oshieru?manabu? I still don't remember which is which :| – quetzalcoatl Oct 27 '20 at 14:16

1 Answers1

0

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.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524