代码之家  ›  专栏  ›  技术社区  ›  user10118324

std::hash与模板参数的专业化

  •  1
  • user10118324  · 技术社区  · 1 年前

    我有以下模板化的数据结构

    #include <cinttypes>
    #include <cfloat>
    #include <type_traits>
    #include <algorithm>
    
    constexpr bool is_base_2(uint64_t number){
        return (number != 1) && ((number & (number - 1)) == 0);
    }
    
    constexpr uint64_t power(uint64_t number, uint8_t index){
        uint64_t current{number};
        for(uint8_t i{1}; i <= index; i++){
            current *= number;
        }
        return current;
    }
    
    
    
    // implementation details: https://en.wikipedia.org/wiki/Fixed-point_arithmetic
    template <
            std::size_t size,
            uint64_t scaling_factor_inverse,
            bool is_signed = true,
            typename = typename std::enable_if_t<is_base_2(scaling_factor_inverse)>,
            typename UnderlyingIntegerType =
                typename std::conditional_t<(size == 16) && is_signed,
                    std::int16_t,
                typename std::conditional_t<(size == 16) && !is_signed,
                    std::uint16_t,
                typename std::conditional_t<(size == 32) && is_signed,
                    std::int32_t,
                typename std::conditional_t<(size == 32) && !is_signed,
                    std::uint32_t,
                typename std::conditional_t<(size == 64) && is_signed,
                    std::int64_t,
                typename std::conditional_t<(size == 64) && !is_signed,
                    std::uint64_t,
                    void
                >>>>>
            >
    >
    class fixed{
    
    friend struct std::hash<fixed<size, scaling_factor_inverse, is_signed>>;
    
    public:
    
        template <
                typename Number,
                typename std::enable_if_t<std::is_arithmetic_v<Number> , int> = 0>
        fixed(const Number& number){
            static_assert(
                std::is_signed_v<Number> ? is_signed : true,
                "cannot create unsigned fixed-point from signed arithmetic type"
            );
            data = number * scaling_factor_inverse;
        }
    
        fixed( const fixed & ) = default;
    
        template<
            typename Number,
            typename = typename std::enable_if_t<std::is_arithmetic_v<Number>>
        >
        operator Number() const
        {
            static_assert(
                std::is_unsigned_v<Number> ? !is_signed : true,
                "cannot convert signed fixed-point to an unsigned arithmetic type"
            );
            return
            static_cast<Number>(
                static_cast<long double>(data) /
                static_cast<UnderlyingIntegerType>(scaling_factor_inverse)
            )
            ;
        }
    
    
    private:
    
        UnderlyingIntegerType data;
        fixed() = default;
    
    };
    
    template<std::size_t Size, uint64_t ScalingFactorInverse, bool Signed>
    struct std::hash<fixed<Size, ScalingFactorInverse, Signed>>{
            std::size_t operator()(fixed<Size, ScalingFactorInverse, Signed> number) const {
            static std::hash<decltype(number.data)> hasher{};
            return hasher(number.data);
        }
    };
    

    我正试图为这个类创建std::hash的专业化,如下所示

    template<std::size_t Size, uint64_t ScalingFactorInverse, bool Signed>
    struct std::hash<fixed<Size, ScalingFactorInverse, Signed>>{
            std::size_t operator()(fixed<Size, ScalingFactorInverse, Signed> number) const {
            static std::hash<decltype(number.data)> hasher{};
            return hasher(number.data);
        }
    };
    

    但我收到一个编译错误

    error: expected parameter declarator
            std::size_t operator()(fixed<Size, ScalingFactorInverse, Signed> number) const {
                                   ^
     src/main/util/fixed_point.h:181:74: error: expected ')'
            std::size_t operator()(fixed<Size, ScalingFactorInverse, Signed> number) const {
                                                                             ^
    

    我一直无法确定这个问题的原因,如果有人能给我指明正确的方向,我将不胜感激。

    请对我温柔一点。

    我已尝试替换

        std::size_t operator()(fixed<Size, ScalingFactorInverse, Signed> number) const {
    

    但我认为这可能会在其他地方引起问题(我不确定?)。

    1 回复  |  直到 1 年前
        1
  •  4
  •   Ted Lyngmo    1 年前

    您需要添加 :: fixed 在中 operator() 否则 也许 拿起 std::fixed 哪个是 作用 在中 std 命名空间(您的专业化所在的位置):

    template<std::size_t Size, uint64_t ScalingFactorInverse, bool Signed>
    struct std::hash<fixed<Size, ScalingFactorInverse, Signed>>{
        std::size_t operator()(::fixed<Size, ScalingFactorInverse, Signed> number) const {
    //                         ^^
            static std::hash<decltype(number.data)> hasher{};
            return hasher(number.data);
        }
    };