It is called template specialization and works as follows:
#include <cstdint>
#include <iostream>
struct Container1 {
static constexpr size_t size = 5;
};
struct Container2 {
static constexpr size_t size = 3;
};
template <typename Container>
struct Point {
Container container;
void bar() {
this->bar_templated<Container::size>();
}
private:
template<std::size_t size>
void bar_templated() {
std::cout << "default\n";
}
template<>
void bar_templated<3>() {
std::cout << "specialized <3>\n";
}
template<>
void bar_templated<5>() {
std::cout << "specialized <5>\n";
}
};
int main(){
Point<Container1> p1;
p1.bar();
Point<Container2> p2;
p2.bar();
}
output
specialized <5>
specialized <3>
due to bug 85282 in gcc making it impossible to compile an explicit specialization in non-namespace scope (thanks @songyuanyao), there are errors:
25:14: error: explicit specialization in non-namespace scope 'struct Point'
26:27: error: template-id 'bar_templated<3>' in declaration of primary template
...
30:10: error: 'void Point::bar_templated()' cannot be overloaded
But you can workaround this by moving the functions out of the class and still achieve specialization:
template<std::size_t size>
void bar_templated() {
std::cout << "default\n";
}
template<>
void bar_templated<3>() {
std::cout << "specialized 3\n";
}
template<>
void bar_templated<5>() {
std::cout << "specialized 5\n";
}
template <typename Container>
struct Point {
Container container;
void bar() {
bar_templated<Container::size>();
}
};
This way the functions are public, which may not be what you want, though. Well, if you're writing inside a header file you could define them inside an anonymous namespace.
Also: if constexpr - but that's only C++17 and forward. It reducing the code size by alot and keeping it's logical nature makes it the best approach here, for sure.
void bar() {
if constexpr (Container::size == 3) {
std::cout << "specialized <3>\n";
}
else if constexpr (Container::size == 5) {
std::cout << "specialized <5>\n";
}
}