Member Function Templates

Learn how to create and use member function templates in classes and structs, including syntax, instantiation, and advanced techniques
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, Unlimited Access
Illustration representing computer hardware
Ryan McCombe
Ryan McCombe
Posted

Building on our previous lesson on function templates, we now expand our knowledge to templates for member functions.

As we might expect, these templates can be instantiated to create functions within the scope of a class or a struct. In this lesson, we’ll cover:

  • The syntax for defining member function templates
  • How to instantiate and call member function templates
  • Using member function templates in class templates
  • How to separate declarations from definitions
  • Important considerations when using header and implementation files

Creating Member Function Templates

The syntax for member function templates is identical to those of regular function templates. We provide a list of template parameters, followed by the body of our template.

Below, we define Attack as a member function template within the Player class:

#include <iostream>

class Monster {/*...*/}; class Player { public: template <typename T> void Attack(T Target) { std::cout << "\nAttacking " << Target.Name; } std::string Name; }; int main() { Player PlayerOne{"Anna"}; Player PlayerTwo{"Roderick"}; PlayerOne.Attack<Player>(PlayerTwo); Monster Goblin{"Bonker"}; PlayerOne.Attack<Monster>(Goblin); }
Attacking Roderick
Attacking Bonker

Naturally, the functions generated by a member function template have all the same capabilities of a member function. For example, they can access the this pointer, call other member functions, and access member variables in the context of the current object:

#include <iostream>

class Monster {/*...*/}; class Player { public: template <typename T> void Attack(T Target) { std::cout << Name << " is attacking " << Target.Name << '\n'; } std::string Name; };
int main() {/*...*/}
Anna is attacking Roderick
Anna is attacking Bonker

When the compiler can deduce which function needs to be instantiated from the template based on our function arguments, we can remove the template arguments:

#include <iostream>

class Monster {/*...*/};
class Player {/*...*/}; int main() { Player PlayerOne{"Anna"}; Player PlayerTwo{"Roderick"}; PlayerOne.Attack<Player>(PlayerTwo); PlayerOne.Attack(PlayerTwo); Monster Goblin{"Bonker"}; PlayerOne.Attack<Monster>(Goblin); PlayerOne.Attack(Goblin); }
Anna is attacking Roderick
Anna is attacking Bonker

Member Templates in Template Classes

Sometimes, we’ll be creating member function templates within a class that itself will be an instance of a template:

template <typename ClassParameter>
class SomeClassTemplate {
  template <typename FunctionParameter>
  void SomeFunctionTemplate() {
    // ...
  }
};

In this scenario, our member function template will also have access to the class template arguments.

We’ve updated our previous example to make Player a class template, rather than an individual class. It accepts a template argument specifying the preferred combat style of the class it creates:

#include <iostream>

enum class Style { Melee, Magic };

class Monster {/*...*/}; template <Style CombatStyle> class Player { public: template <typename T> void Attack(T Target) { std::cout << Name << " is attacking " << Target.Name; if (CombatStyle == Style::Melee) { std::cout << " with a sword\n"; } else { std::cout << " with magic\n"; } } std::string Name; }; int main() { Player<Style::Magic> PlayerOne{"Anna"}; Monster Goblin{"Bonker"}; PlayerOne.Attack(Goblin); Player<Style::Melee> PlayerTwo{"Roderick"}; PlayerTwo.Attack(PlayerOne); }
Anna is attacking Bonker with magic
Roderick is attacking Anna with a sword

The previous example used template argument deduction to allow us to simply write Attack(Goblin) instead of Attack<Monster>(Goblin). We can specify the template arguments if preferred and, in some scenarios, we will need to.

However, now that Player is a class template, we can no longer use it in scenarios where a type is expected.

When we have a template, and we need a type, we have to provide the template arguments that will generate that type, such as Player<Style::Magic>:

#include <iostream>

enum class Style { Melee, Magic };

class Monster {/*...*/};
class Player {/*...*/}; int main() { Player<Style::Magic> PlayerOne{"Anna"}; Monster Goblin{"Bonker"}; PlayerOne.Attack<Monster>(Goblin); Player<Style::Melee> PlayerTwo{"Roderick"}; PlayerTwo.Attack<Player<Style::Magic>>( PlayerOne); }
Anna is attacking Bonker with magic
Roderick is attacking Anna with a sword

Remember: we can introduce type aliases as needed to make our code easier to understand:

#include <iostream>

enum class Style { Melee, Magic };

class Monster {/*...*/};
class Player {/*...*/}; int main() { using MeleePlayer = Player<Style::Melee>; using MagicPlayer = Player<Style::Magic>; MagicPlayer PlayerOne{"Anna"}; Monster Goblin{"Bonker"}; PlayerOne.Attack<Monster>(Goblin); MeleePlayer PlayerTwo{"Roderick"}; PlayerTwo.Attack<MagicPlayer>(PlayerOne); }
Anna is attacking Bonker with magic
Roderick is attacking Anna with a sword

Defining Member Templates Separately

If we want to separate the declaration of a member function template from its implementation, our code could look something like this:

#include <iostream>

class Player {
 public:
  template <typename T>
  void Attack(T Target);

  std::string Name;
};

template <typename T>
void Player::Attack(T Target) {
  std::cout << "\nAttacking " << Target.Name;
}

Where the template function is part of a template class, our implementation would have two sets of template arguments - one for the class, and one for the function.

Additionally, we need to fully qualify what class we’re providing an implementation for, by including the template arguments. With these two considerations combined, our code would look something like this:

#include <iostream>
enum class Style { Melee, Magic };

class Player {/*...*/}; template <Style CombatStyle> template <typename T> void Player<CombatStyle>::Attack(T Target) { std::cout << Name << " is attacking " << Target.Name; if (CombatStyle == Style::Melee) { std::cout << " with a sword\n"; } else { std::cout << " with magic\n"; } }

In the previous examples, we assume the declaration and definition are within the same file. If we want to split them across different files - such as a header file an and implementation file - there are some additional problems to overcome.

We introduced these problems, and options for working around them, earlier in the chapter:

Summary

In this lesson, we learned about member function templates in C++. The key takeaways are:

  • Member function templates allow us to create generic functions within classes and structs
  • The syntax is similar to regular function templates, with the template parameters defined before the function
  • Member function templates can access the class's member variables and functions
  • When the class is also a template, the member function template has access to the class template parameters
  • Defining member function templates separately requires fully qualifying the class name with its template arguments
  • Additional considerations are needed when using member function templates across header and implementation files

Was this lesson useful?

Next Lesson

Template Specialization

A practical guide to template specialization in C++ covering full and partial specialization, and the scenarios where they’re useful
Illustration representing computer hardware
Ryan McCombe
Ryan McCombe
Posted
Lesson Contents

Member Function Templates

Learn how to create and use member function templates in classes and structs, including syntax, instantiation, and advanced techniques

A computer programmer
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, Unlimited Access
Templates
A computer programmer
This lesson is part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Template Specialization

A practical guide to template specialization in C++ covering full and partial specialization, and the scenarios where they’re useful
Illustration representing computer hardware
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved