仅在模板化类的特定特化上声明成员函数

  • 本文关键字:声明 函数 成员 c++ c++14
  • 更新时间 :
  • 英文 :


我有一个模板类来帮助在编译时计算物理量。它使用额外的模板参数(std::ratio)来确保像Length这样的东西只能添加到Length,或者AreaLength乘以Length

#include <ratio>
template <
typename Length      = std::ratio<0>, // Meter
typename Mass        = std::ratio<0>, // Kilogram
typename Time        = std::ratio<0>, // Second
typename Current     = std::ratio<0>, // Ampere
typename Temperature = std::ratio<0>, // Kelvin
typename Amount      = std::ratio<0>, // Mole
typename Luminous    = std::ratio<0>  // Candela
>
class Quantity {
private:
double value;
public:
constexpr Quantity(double val) : value(val) {}
Quantity &operator+=(Quantity const &that) {
value += that.value;
return *this;
}
// ...
};

但有时我想转换回一个简单的double,与其他东西的接口。

我可以为模板化类添加一个成员函数,它返回内部的double,或者在需要double时允许隐式(或显式)转换为double

constexpr double getValue() { return value; }
constexpr operator double() { return value; }

然而,我真的只希望这种隐式转换发生在"维度"的数量均为0(模板参数均为0)。

我可以只声明相同的成员函数,并且只定义我想要的专门化。但这仍然声明,对于我不希望允许转换的类型,存在转换(你应该先除以你想要的单位)。这使得我的编辑器告诉我它是好的,但它不会在编译时链接。

是否有一种方法可以仅在特定的特化上声明成员函数?

值得注意的是,我现在被困在c++ 14上,否则我认为if constexpr可以工作…

不能,if constexpr不能用于提供类方法的条件定义。if constexpr属于某个方法或函数,因此需要在使用if constexpr做任何事情之前声明它,并且您的目标是甚至不声明它。

没有办法直接为特定的特化或模板实例实例化类方法,但是有一种常见的方法非常接近:模拟重载解析失败。

下面是一个简化的例子:

#include <type_traits>
#include <iostream>
template<typename T>
struct life {
template<typename=
typename std::enable_if<std::is_same<T,int>::value>::type>
constexpr int answer()
{
return 42;
}
};
int main()
{
life<int> of_brian;
std::cout << of_brian.answer() << std::endl; // Shows 42
life<double> of_black_night;
std::cout << of_black_night.answer() << std::endl; // Error
return 0;
}

模板类只对其int实例有效地实现answer()gcc的错误消息,对于试图从不需要的模板实例调用它是:

错误:调用' life::answer() '没有匹配的函数

和"this doesn't exist, pal"非常相似。

这在逻辑上与你试图对模板做的事情是等同的,唯一的区别是你需要检查一堆模板参数,而不是一个。

最新更新