Это называется специализацией шаблона и работает следующим образом:
#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();
}
вывод
specialized <5>
specialized <3>
из-за ошибка 85282 в gcc* * * * * * * * * * * * * * * * * * * (спасибо @songyuanyao):
25: 14: ошибка: явная специализация в не-пространстве имен: невозможно скомпилировать явную специализациюобласть видимости "struct Point"
26: 27: ошибка: идентификатор шаблона 'bar_templated <3>' в объявлении основного шаблона
...
30: 10:ошибка: 'void Point :: bar_templated ()' не может быть перегружен
Но вы можете обойти это, переместив функции из класса и все же достигнув специализации:
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>();
}
};
Таким образом, функции являются общедоступными, что может не соответствовать вашим ожиданиям.Что ж, если вы пишете в заголовочном файле, вы можете определить их в анонимном пространстве имен.
Также: , если constexpr - но это только C ++ 17 и вперед.Это уменьшает размер кода на много и сохраняет его логическую природу, что делает его лучшим подходом здесь, конечно.
void bar() {
if constexpr (Container::size == 3) {
std::cout << "specialized <3>\n";
}
else if constexpr (Container::size == 5) {
std::cout << "specialized <5>\n";
}
}