类型组模板化类的成员专门化
Member specialization for a templated class for groups of types?
我有一个矩阵类,我想为不同的矩阵类型(int, float, double)将矩阵打印到终端。我想实现这个:
- 如果矩阵类型为
int
,则使用printf("%d ",matrix[i][j])
打印矩阵 - 如果矩阵类型为
float
或double
,则使用printf("%.3f ",matrix[i][j])
打印矩阵 - 否则抛出错误
以下是我所拥有的相关部分:
...
template <class T>
class Matrix2D {
private:
std::vector< std::vector<T> > matrix;
public:
...
void print() const; // print the whole matrix
}
...
template <class T>
void Matrix2D<T>::print() const {
// throw an error
}
template <>
void Matrix2D<int>::print() const {
// print matrix using printf("%d ",matrix[i][j])
}
template <>
void Matrix2D<float,double>::print() const {
// print matrix using printf("%.3f ",matrix[i][j])
}
但是使用Matrix2D<float,double>
给了我错误信息error: wrong number of template arguments (2, should be 1)
。然而,我想对float
和double
类型矩阵都有一个通用的print()
函数(不想复制相同的东西两次)。实现这一目标的最简单方法是什么?谢谢!
只是作为建议的模板解决方案的替代方案,使用旧的好的函数重载:
public:
void print() const
{
for (auto const& row : matrix)
for (auto const& v : row)
print(v);
}
private:
static void print(int val)
{
printf("%d ", val);
}
static void print(float val)
{
printf("%.3f", val);
}
问题要求Matrix2D<short>::print()
抛出错误。为了达到这个目的,你可以使用标签调度。
标签- simple
naïve方法要求您直接为每种类型专门标记。
namespace detail
{
struct int_tag{};
struct float_tag{};
struct error_tag{};
template<typename T> struct choose_tag { using type = error_tag; };
template<> struct choose_tag<int> { using type = int_tag; };
template<> struct choose_tag<double> { using type = float_tag; };
template<> struct choose_tag<float> { using type = float_tag; };
template<typename T>
using tag = typename choose_tag<T>::type;
}
标签-类型列表
使用Boost可以避免这种情况。Hana(或其他MPL解决方案)。首先,为列表中的类型定义check:
template<typename T, typename... Us>
constexpr bool contains =
hana::any_of(hana::tuple_t<Us...>, hana::partial(hana::equal, hana::type_c<T>))();
然后enable_if
这个类型为你的标签:
template<typename T, typename = std::void_t<>>
struct choose_tag
{ using type = error_tag; };
template<typename T>
struct choose_tag<T, enable_if_t<contains<T, int>>>
{ using type = int_tag; };
template<typename T>
struct choose_tag<T, enable_if_t<contains<T, double, float>>>
{ using type = float_tag; };
Common - print
实现
然后声明使用它们的函数模板:
template<typename T>
void print_matrix(detail::int_tag, T&&) {
cout << __PRETTY_FUNCTION__ << endl;
}
template<typename T>
void print_matrix(detail::float_tag, T&&) {
cout << __PRETTY_FUNCTION__ << endl;
}
template<typename T>
void print_matrix(detail::error_tag, T&&) {
cout << __PRETTY_FUNCTION__ << endl;
}
和电话:
template <class T>
class Matrix2D {
private:
std::vector< std::vector<T> > matrix;
public:
void print() const {
print_matrix(detail::tag<T>{}, *this);
}
};
下面是简单和类型列表版本的实例
您可以使用enable_if
和类型特征,做这样的事情:
template<class T> class MyClass
{
public:
// this one will be created if the argument is of a floating point type, i.e.
// double or float
template<typename U = T>
typename std::enable_if<std::is_floating_point<U>::value, void>::type
print(U v)
{
std::cout << "float" << std::endl;
}
// this one will be created if the argument is of an integral type, i.e.
// bool, char, char16_t, char32_t, wchar_t, short, int, long, long long
template<typename U = T>
typename std::enable_if<std::is_integral<U>::value, void>::type
print(U v)
{
std::cout << "integer" << std::endl;
}
};
int main() {
MyClass<int>c;
c.print(1);
c.print(1.f);
}
输出:integer
float
相关文章:
- 如何基于模板化类的基类专门化成员函数
- 根据成员容器的尺寸,专门化成员功能
- 专门化一个成员函数,而不是整个类
- c++多参数模板化的类成员专门化
- C++ : 如何为模板类 A 专门化成员函数来处理类似数组的类 A<T>< >?
- 使用已推导的模板参数专门化模板成员函数
- C++专门化成员功能
- 根据类成员的存在/不存在专门化C++模板
- 如何根据类的模板参数专门化模板成员函数?
- 如何为具有位字段成员的类专门化“swap”
- 成员和成员函数的模糊部分模板专门化
- C++中模板类的成员函数的专门化
- 专门化模板成员函数来处理std::string和char[]参数
- 如何专门化此模板成员函数
- C++-专门化Template类的成员函数
- 专门化模板成员函数
- 可变模板成员函数的部分专门化
- 类型组模板化类的成员专门化
- 部分成员专门化
- 使用IBM Rational Rhapsody的显式成员专门化