【问题标题】:Determine highest precision type for corresponding floating point and complex types确定相应浮点和复杂类型的最高精度类型
【发布时间】:2020-12-28 15:14:42
【问题描述】:

推导出浮点和复杂类型的最高精度类型,即

  • float/double/long double 导致long double
  • std::complex<T> 导致std::complex<long double>

我的尝试 (live example on Wandbox) 感觉很笨拙:

#include <complex>
#include <type_traits>

template <typename T>
struct is_complex : std::false_type {};

template <std::floating_point T>
struct is_complex<std::complex<T>> : std::true_type {};

template <typename T>
inline constexpr bool is_complex_v = is_complex<T>::value;

template <typename T>
struct highest_precision_type
{
    // none for arbitrary type
};

template <typename T>
    requires std::is_floating_point_v<T>
struct highest_precision_type<T>
{
    typedef long double type;
};

template <typename T>
    requires is_complex_v<T>
struct highest_precision_type<T>
{
    typedef std::complex<long double> type;
};

int main()
{
    auto f  = highest_precision_type<float>::type{1};
    auto cf = highest_precision_type<std::complex<float>>::type{0, 1};
    
    static_assert(std::is_same_v<decltype(f), long double> );
    static_assert(std::is_same_v<decltype(cf), std::complex<long double>> );
}

有没有更简洁的方法来达到预期的效果?

【问题讨论】:

  • IIRC、long doublestd::complex&lt;long double&gt; 保证始终是最高精度。
  • @NathanOliver:同意。 highest_precision_type&lt;T&gt; 旨在用于模板代码中,以将中间值提​​升到这些最高精度类型,以减少舍入和取消错误。
  • @RenéRichter 对于您的目标,这对我来说似乎是合理的。感觉笨拙?好吧,C++ 元编程非常笨拙。
  • 除非你可以template&lt;typename T&gt; struct highest_precision_type&lt;std::complex&lt;T&gt;&gt; { ...} 你的代码看起来很棒。好吧,所以,你需要定义如何衡量“简洁性”以及如何准确减少代码的“笨拙感”,否则你的问题只是基于意见。

标签: c++ c++20


【解决方案1】:

使用std::conditional&lt;&gt; 和@KamilCuk 的注释将代码简化为:

template <typename T>
struct highest_precision_type
    : std::conditional<std::is_floating_point_v<T>, long double, T>
{
};

template <typename T>
struct highest_precision_type<std::complex<T>>
{
    typedef std::complex<long double> type;
};

live example

【讨论】:

    【解决方案2】:

    我认为您的代码很好,但如果您想要更紧凑的替代方案,可以使用std::conditional

    template <typename T>
    struct highest_precision_type
    {
        static_assert(std::is_arithmetic_v<T>);
    
        using type = 
            std::conditional_t<
                std::is_unsigned_v<T>,
                std::uintmax_t,
                std::conditional_t<
                    std::is_integral_v<T>,
                    std::intmax_t,
                    long double>
            >;
    };
    

    对于从模板实例化的类型,Barry 在他现在已删除的答案中的内容看起来不错。这是我的看法:

    template <template <typename...> class C, typename... Ts>
    struct highest_precision_type<C<Ts...>>
    {
        using type = C<typename highest_precision_type<Ts>::type...>;
    };
    
    template <typename T>
    using highest_precision_type_t = typename highest_precision_type<T>::type;
    

    Demo

    注意演示中的部分:

    highest_precision_type_t<std::string> s;
    static_assert(std::is_same_v<decltype(s), std::basic_string<std::intmax_t>>);
    

    【讨论】:

      猜你喜欢
      • 2021-08-30
      • 1970-01-01
      • 2023-04-01
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多