【问题标题】:Understanding code duplication in template specializations of std::complex<T>了解 std::complex<T> 的模板特化中的代码重复
【发布时间】:2022-01-16 03:03:21
【问题描述】:

我正在查看 C++ 标准库的 &lt;complex&gt; 实现。我注意到对于所有当前的 GNU、LLVM 和 MSVC 实现,对于类型 float doublelong double 的模板特化存在大量代码重复,但我不知道为什么。

https://github.com/microsoft/STL/blob/main/stl/inc/complex的MSVC代码为例,考虑类模板及其特化

template <class _Ty>
class complex;
template <>
class complex<float>;
template <>
class complex<double>;
template <>
class complex<long double>;

通用类模板中已有定义。以operator*=的一个定义为例,

template <class _Ty>
class complex : public _Complex_base<_Ty, _Complex_value<_Ty>> {
public:
    // ...
    _CONSTEXPR20 complex& operator*=(const _Ty& _Right) {
        this->_Val[_RE] = this->_Val[_RE] * _Right;
        this->_Val[_IM] = this->_Val[_IM] * _Right;
        return *this;
    }
    // ...
};

为什么floatdoublelong double的特化中的几乎所有成员函数都会一次又一次地重复这种代码,如下所示?

template <>
class complex<double> : public _Complex_base<double, _Dcomplex_value> {
public:
    // ...
    _CONSTEXPR20 complex& operator*=(const _Ty& _Right) {
        _Val[_RE] = _Val[_RE] * _Right;
        _Val[_IM] = _Val[_IM] * _Right;
        return *this;
    }
    // ...
};

std::complex&lt;T&gt; 的模板特化中出现这种代码重复的原因是什么?


供参考,在上面的MSVC代码中,是

using _Dcomplex_value = _CSTD _C_double_complex;

作为参考,&lt;complex&gt; 的 GNU 实现可以在 https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/complex 找到

作为参考,&lt;complex&gt; 的 LLVM 实现可以在 https://github.com/llvm/llvm-project/blob/main/libcxx/include/complex 找到

作为参考,&lt;complex&gt; 的 MSVC 实现可以在https://github.com/microsoft/STL/blob/main/stl/inc/complex 的 MSVC 代码中找到

【问题讨论】:

  • 我认为_Dcomplex_value_Complex_value&lt;double&gt; 在某些方面不同
  • 在他们的 github 网站上打开一个问题并询问实际作者不是更好吗?
  • 看来_C_double_complexcomplex.h 的C 库实现共享,也许共享结构确保C++ std::complex&lt;double&gt; 和C double complex 是ABI 兼容的。

标签: c++ templates template-specialization c++-standard-library


【解决方案1】:

这种代码重复的原因是什么

简答:return *this

您需要在特化中定义每个运算符才能返回正确的类型。否则它们会返回对基类的引用。

可以在派生类中调用基类操作符,比如

    _CONSTEXPR20 complex& operator*=(const _Ty& _Right) {
       _Complex_base<_Ty, _Complex_value<_Ty>>::operator*=(_Right);
       return *this;
   }

但是,即使它减少了重复,它实际上并没有减少代码大小,或者使它更具可读性。

【讨论】:

  • 模板版本也将返回正确的类型。不知道应该有什么不同...
  • @Klaus - 是的,但您需要具备专业知识,因为转换构造函数略有不同。一旦你在那里,你还需要派生类中的运算符。
  • 对不起,不 :-) 您也可以将通用部分作为完全非专业化的版本,而在专业化中使用其他不同的东西。从技术上讲,没有理由复制相同的代码。但有时简单地复制粘贴这些东西,在需要的地方做一些小改动并将其打包到一个文件中会更容易:-)
猜你喜欢
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 2017-09-12
  • 2019-04-03
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多