0

How to swap 2 objects using template function ??? I just want to swap the age number between 2 objects from same class using template function called my_swap().

struct Men
{
    std::string name;
    int age;
}
std::ostream &operator<<(std::ostream &os,const Men &M)
{
    os << M.name;
    return os;
}


template <typename T>
void my_swap(T &a,T &b)
{
    T temp = a;
    a = b;
    b= temp;
}

int main()
{
    int x{100};
    int y{200};
    my_swap(x,y);
    std::cout << x << "," << y << std::endl;
}

What I want to do is:

Men M1{"Jack", 10};
Men M2{"Tony", 20};
Men M3 = my_swap(M1, M2);
anastaciu
  • 23,467
  • 7
  • 28
  • 53
logan_92
  • 117
  • 9
  • 4
    `my_swap` has return type `void`, so what exactly are you expecting to receive in `M3`? – UnholySheep Oct 06 '20 at 17:22
  • 2
    You can use `std::swap`, as it is a template function. Already tested and debugged. :-) – Thomas Matthews Oct 06 '20 at 17:24
  • 1
    so if i use T &my_swap(T &a,T &b) , is this work also with primitive types?? also i think i need to change the function implementation to be a.name and b.name. i think i can't make this function to be template function for my own classes and primitive types at same time – logan_92 Oct 06 '20 at 17:26
  • 1
    OT: `my_swap` shoud use _move semantics_, otherwise it would be terribly inefficient. – Daniel Langr Oct 06 '20 at 17:43
  • 2
    You say you want it to just swap the ages, buy you also say you want it to work with primitive types - which of course don't have an age. Is that correct? – ROX Oct 06 '20 at 17:44
  • Also, what would you want M3 to be set to in your example? – ROX Oct 06 '20 at 17:45
  • Yes @ROX this is correct , i can get rid of M3 , i only want to implement real template function that can work with all primitive types and also my user defined classes – logan_92 Oct 06 '20 at 18:16

2 Answers2

1

Your template is already good to do this, you just have to pass the age member in the call, leaving the template as is:

int main()
{
    Men M1{"Jack", 10};
    Men M2{"Tony", 20};
    my_swap(M1.age, M2.age); //pass the ages only
    std::cout << M1 << "," << M2 << std::endl;
}

Live demo


Or you can do something like:

//...
template <typename T>
void my_swap(T &a, T &b)
{
    T temp;
    temp.age = a.age;
    a.age = b.age;
    b.age = temp.age;
}

int main()
{
    Men M1{"Jack", 10};
    Men M2{"Tony", 20};
    my_swap(M1, M2); //pass the objects
    std::cout << M1 << "," << M2 << std::endl;
}

Live demo

This would only swap the age of the Men objects passed as arguments.


Using:

std::ostream &operator<<(std::ostream &os, const Men &M)
{
    os << M.name << " " << M.age;
    return os;
}

Both examples would output:

Jack 20,Tony 10

The line:

Men M3 = my_swap(M1, M2);

Is not correct, your template has void return type it cannot be assigned.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • ok so this template function only work with men class?? i can't use it with primitive data types?? – logan_92 Oct 06 '20 at 17:40
  • @logan_92, your original template works with primitive types also, yes, it's exactly what I do in the first code sample I posted, it swaps the age member of the 2 classes. – anastaciu Oct 06 '20 at 17:53
  • thank you @anastaciu , but i think for 1st approach we have to change my_swap() implementation to be T temp.age = a??? – logan_92 Oct 06 '20 at 18:04
  • @logan_92, I don't think it's needed, I added an online sample to the answer, check it out. – anastaciu Oct 06 '20 at 18:22
  • @logan_92, I also added an online sample for the second code, but the first is better IMO as it's more generic. – anastaciu Oct 06 '20 at 18:25
1

Your my_swap() template function does a complete swap. If you want it to swap only the age fields of Men parameters, and do a complete swap for other types, then you can use template specialization to accomplish that, eg:

template <typename T>
void my_swap(T &a,T &b) // <-- primary template for all types
{
    T temp = std::move(a);
    a = std::move(b);
    b = std::move(temp);

    /* or:
    using std::swap;
    swap(a, b);
    */
}

...

struct Men
{
    std::string name;
    int age;
};

template <>
void my_swap<Men>(Men &a, Men &b) // <-- specialization just for Men only
{
    int temp = a.age;
    a.age = b.age;
    b.age = temp;

    /* or:
    std::swap(a.age, b.age);
    */
}

std::ostream &operator<<(std::ostream &os, const Men &M)
{
    os << M.name << " is " << M.age;
    return os;
}

int main()
{
    int x{100};
    int y{200};
    my_swap(x, y);
    std::cout << x << "," << y << std::endl;

    Men M1{"Jack", 10};
    Men M2{"Tony", 20};
    my_swap(M1, M2);
    std::cout << M1 << "," << M2 << std::endl;
}

Output:

200,100
Jack is 20,Tony is 10

Live Demo

This way, the specialization is used whenever my_swap() is called with T set to Men, and the primary template is used whenever my_swap() is called with T set to any other type.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • thank you for the answer, but is this normal function or template function ?? what does template <> mean , and how can you use my_swap in template function declaration ?? is this concept called template specialization?? template <> void my_swap(Men &a, Men &b) – logan_92 Oct 06 '20 at 22:14
  • @logan_92 It is a [full specialization](https://en.cppreference.com/w/cpp/language/template_specialization) of a template function. `template <>` means the original template is being fully specialized with specific template parameter values, and so can have different code than the original. In this case, the specialized template is used for calls to `my_swap(Men&,Men&)` and the original template is used for all other calls to `my_swap()`. I suggest you read up on template specialization in any [decent C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) – Remy Lebeau Oct 06 '20 at 22:40