称为模板特化,工作原理如下:
#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>
由于 gcc 中的bug 85282 使其成为impossible to compile an explicit specialization in non-namespace scope(感谢@songyuanyao),出现错误:
25:14:错误:非命名空间范围“结构点”中的显式特化
26:27:错误:主模板声明中的模板 ID 'bar_templated'
...
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>();
}
};
这样,函数是公开的,但这可能不是你想要的。好吧,如果你在头文件中编写,你可以在匿名命名空间中定义它们。
另外:if 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";
}
}