当前位置: 首页 > 知识库问答 >
问题:

如何根据类型是整型还是浮点型更改模板方法?

蒯硕
2023-03-14

我正在研究一个矩阵类,它采用整数(short,int,long)和浮点类型(float,double)。我希望某些方法仅限于浮点类型(例如反转方法),而某些方法对于浮点类型和整数类型(例如==运算符)具有不同的实现。我有一种预感,正确的方法是使用boost的“enable_if”和“is_integral”/“is_floating_point”,但我似乎无法让它工作。

我的实现类似于此c半伪代码:

template <typename T>
class Matrix
{
    ...
    bool operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const;
    bool operator==(Matrix<typename enable_if<is_floating_point<T>::type T> >) const;
    typename enable_if<is_floating_point<T> T> computeInverse() const;
    ...
};
// implementation
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const {
  //implementation without precision
}
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const {
  //implementation using precision
}
Matrix<typename enable_if<is_floating_point<T> T>::type > Matrix<T>::computeInverse() const {
  //implementation requiring floating points
}

这会产生很多编译错误,而我认为这些是最相关的错误:

error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_integral<float>, float>’

error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_floating_point<int>, int>’

这表明我不能为不同的类型使用不同的实现,至少不能使用boost的enable_if,这是否正确?

如果是这样,我该怎么做?我知道模板专门化是一种方法,但是我想避免重复太多的代码。

共有2个答案

钱毅
2023-03-14

您应该尝试并遵循@DavidRodriguez的建议,将类的公共功能划分为基类;然后在功能不同的地方提供整个派生类的专门化。这将是更好的办法。

如果您确实希望保留当前实现,则可以按如下方式将不需要的运算符版本从重载解决方案中删除:

#include <iostream>
#include <type_traits>

template<class T>
struct Matrix
{
  // ...
};

template<class T>
typename std::enable_if<
    std::is_integral<T>::value, bool
  >::type
operator==( const Matrix<T>&, const Matrix<T>& )
{
  std::cout << "Integer version" << std::endl;
  return true;
}

template<class T>
typename std::enable_if<
    !std::is_integral<T>::value, bool
  >::type
operator==( const Matrix<T>&, const Matrix<T>& )
{
  std::cout << "Floating point version" << std::endl;
  return true;
}

int main()
{
  Matrix<int> m1, m2;
  Matrix<double> m3, m4;

  if( m1 == m2 ) {}

  if( m3 == m4 ) {}
}

如果您希望操作符作为成员函数,我所知道的使其工作的唯一方法是向操作符添加一个虚拟模板参数并添加

栾烨华
2023-03-14

最简单的方法是在矩阵中使用重载函数:

template <typename T>
class Matrix
{
    template <bool isInteger> class Discrim;
    //  ...
    bool isEqual( Matrix const& other, Discrim<true> ) const
    {
        //  Integer implementation...
    }

    bool isEqual( Matrix const& other, Discrim<false> ) const
    {
        //  Floating point implementation...
    }

public:
    bool isEqual( Matrix const& other ) const
    {
        return isEqual( other, Discrim<std::numeric_limits<T>::is_integer>() );
    }
};

你的运算符==运算符!=当然会调用Matrix::isEqual

话虽如此:从您的评论来看,如果T是浮点类型,您需要一个“几乎相等”的函数。不要这样做。它只会让人感到困惑,并在今后的道路上造成无穷无尽的问题(因为==将不再是一个可传递的操作)。

 类似资料:
  • 我有这样的代码 现在,为了打印值,如果T是一个类,我想调用对象的打印函数,但是如果T是一个基本数据类型,我只想使用printf。 那么,如何确定模板类型是基本数据类型还是类?

  • 问题简述如下: 这里假设T可以是int、float或类的类型。 如果我定义了一些变量并希望使用相同的函数显示它们的值: 我知道,在C中,有一种检查int和float的解决方案(仅针对打印问题),即使用std::cout,如本问题所述(C模板-如何找到模板类型是基本类型还是类)。 使用d::is_integral::值不适用于这样的情况: 因为这些变量是类而不是基本类型。对于这种情况,我们如何判断n

  • 我想编写一个函数模板,它返回各种类型的随机变量(bool、char、short、int、float、double,以及这些变量的无符号版本)。 我看不出如何使用最新的C 11标准库来实现这一点,因为我需要使用统一的int分布或统一的real分布。我想我可以专门化模板: 在Visual Studio 2012 Update 3下,这给出了: 错误C2668:“‘匿名命名空间’::randomPrim

  • 本文向大家介绍PHP浮点数据类型,包括了PHP浮点数据类型的使用技巧和注意事项,需要的朋友参考一下 定义和用法 在PHP中,float数据类型表示任何数字,并带有小数部分。小数部分可以包含小数点后的数字,或者可以使用e或E以科学计数法表示。例如,科学计数法中的100是10e2。 浮点数的大小取决于硬件/ OS平台,尽管通常会精确到小数点后14位。 语法 为了更好的可读性,整数文字可以使用“ _” 

  • 对于雄辩的save方法,是否有一种简单的方法来检查一行是否确实发生了更改?类似于的内容是否有说服力? 我发现的唯一解决方法是从Laravel Eloquent update中获得的,只要做了以下更改: 但是,这是否可以在不需要变量和检查的情况下找到更短的结果?我不想在每个控制器中重复这种逻辑。 我正在寻找这样的东西: 但是这不起作用,因为

  • 我想根据传递给类的模板参数实现一个实现开关: 如果传递的模板类型派生自特定类(此处:Serializable),则创建该类型实例的容器DataElement应派生自SerializableElement,并重载从其继承的两个纯虚拟方法(此处:unloadTo和loadFrom) 然而,如果传递的模板类型不是从Serializable派生的,那么DataElement不应该从Serializable