使用已推导的模板参数专门化模板成员函数
Specialize template member function with already-deduced template parameter
我想根据已经推导的结构模板参数的类型特征来专门化模板结构的成员函数。 当模板参数有符号时,我想要一个版本的函数,当它没有符号时,我想要另一个版本的函数。 不知道该怎么做。
结构很简单。 它代表了一个大小 - 毫无疑问,它已经被写了一千次。 我想这是一个我可以用于所有类型的简单版本:
template<class T>
struct Size
{
T cx;
T cy;
// ... a bunch of functions you might expect.
// normalize function -- avoid negative sizes. make sure size is at LEAST 0, 0
void normalize()
{
cx = std::min(cx, 0);
cy = std::min(cy, 0);
}
};
但是,当然,对于无符号类型,处理函数毫无意义。 我想让它成为这些类型的禁区。
有一秒钟,我想我可能会尝试将enable_if与返回类型一起使用。
typename std::enable_if<std::is_signed<T>::value, Size&>::type
normalize()
{
cx = std::max(cx, 0);
cy = std::max(cy, 0);
return *this;
}
typename std::enable_if<std::is_unsigned<T>::value, Size&>::type
normalize()
{
return *this;
}
但这行不通,因为(据我了解(因为在成员函数的点上,模板"T"已经被推导出来,不能使用 SFINAE。 如果我错了,请纠正我。
所以我想我可以用这样的true_type和false_type写重载:
void normalize(std::true_type)
{
// Ensure signed types are at least zero.
cx = std::max(cx, 0);
cy = std::max(cy, 0);
}
void normalize(std::false_type)
{
// do nothing for unsigned types
}
void normalize()
{
// Call overload based on type.
normalize(std::is_signed<T>::type());
}
但这些似乎毫无意义地构建了一个std::integral_constant<bool>
. 这冒犯了我的效率感。 如果这是一个更复杂的示例,它甚至可能会影响性能。
因此,我可以类似地编写如下所示的成员模板函数:
template <typename T>
void normalizeT()
{ }
template<>
void normalizeT<std::true_type>()
{
cx = std::max(cx, 0);
cy = std::max(cy, 0);
}
void normalize()
{
normalizeT<std::is_signed<T>::type>();
}
我猜还有其他方法。 但我觉得我错过了一些明显的东西。 我总是喜欢花时间把这些东西归结为最简单、最清晰、最强大的版本。
我意识到这不是一个非常复杂的"问题"。 正如我所说,我已经可以让代码工作了,但我正在寻找更普遍的教训 - 理解和识别所涉及的"模式",因为这是我经常遇到的情况。
因此,鉴于这些目标,有没有办法更干净或更健壮地编写它?
不要手动优化(使用模板(。只需让编译器在std::max
上进行优化(注意:您应该使用std::max
来"避免负大小"(
为了澄清起见,或者如果normalize
实际上更复杂,您可以执行以下操作:
void normalize()
{
if(std::is_signed<T>::value) {
cx = std::max(cx, 0);
cy = std::max(cy, 0);
// ...
}
}
除非你正在为嵌入式硬实时系统编写,否则这是过早优化的要点。你应该编写简单明了的代码,即使它看起来不是最佳的。编译器甚至可能足够聪明,可以为您优化对std::max
的调用!如果程序性能可以接受,那么就不会丢失任何内容:您已经编写了一次代码,一切都很好。如果性能成为一个问题,那么您应该分析的不是猜测瓶颈,并且只有当它表明无符号类型的规范化是您的问题领域(我无法想象任何情况都是如此(时,您才会考虑将其专门化为无操作。
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 使用指向成员的指针将成员函数作为参数传递
- 如何将lambda作为模板类的成员函数参数
- 将成员函数指针作为参数传递给模板方法
- c++构造函数成员初始化:传递参数
- 使用带有 ref 参数的成员函数创建线程时出现编译错误
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何将类成员方法的参数列表自动填充写入可变参数?
- 为什么我需要在成员发起器列表中重复基类的模板参数?
- C++向量默认为成员参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 可变参数模板参数扩展 类型为 std::function 的类成员
- 绑定到可变参数成员函数
- C/C++ 包含点的宏参数(成员访问运算符)
- 将const char * const参数成员分配给新值
- 基于模板参数成员函数参数的模板专用化
- 如何访问可变参数成员
- 可变类参数成员变量的异构存储
- 非模板类中的可变参数成员