首页 > 解决方案 > 我怎样才能拥有一个可以通过不同命名空间中的定义参数化数据成员的类?

问题描述

我正在尝试将一堆所有相关的函数移动到一个类中(它们都是静态的),这样该类就可以作为它们周围的一个很好的包装器(我可以在其中指定接口,并使辅助函数私有,等等)。

所以我创建了一个 bigint_to_string 类,我将所有这些函数都放入其中。但后来我意识到有很多东西我希望能够进行配置,例如容器的类型(我可以使用模板),但还有其他参数可能/可能不会从类型。无论我选择哪种风格,只要所有参数都紧密耦合,类(函数)的行为都是相同的。我最初的方法是暂时将参数移出命名空间,如下所示:

4位

  namespace _4bits { // 4 bits -> 0xF per bucket                                                                                                                                             
      constexpr uint8_t BUCKET_BITS{4}; // 4 bits                                                                                                                                            
      using BASE_TYPE = uint8_t;                                                                                                                                                             
      constexpr bool LEFT_SHIFT_HI_BIT_DOES_NOT_OVERFLOW{sizeof(BASE_TYPE)*CHAR_BIT > BUCKET_BITS};                                                                                          
      using CONTAINER = std::vector<BASE_TYPE>;                                                                                                                                              
      constexpr BASE_TYPE MAX{0xF}; // 2**4-1 == 15                                                                                                                                          
      //const auto hi_bit_set = BASE_TYPE(1) << (sizeof(BASE_TYPE) * BITS - 1);                                                                                                              
      constexpr BASE_TYPE hi_bit_set = BASE_TYPE(1) << (BUCKET_BITS - 1); // 0x8 or 0b1000
}

8位

namespace _8bits { // 8 bits -> 0xFF per bucket                                                                                                                                            
      constexpr uint8_t BUCKET_BITS{8}; // 8 bits                                                                                                                                            
      using BASE_TYPE = uint8_t;                                                                                                                                                             
      constexpr bool LEFT_SHIFT_HI_BIT_DOES_NOT_OVERFLOW{sizeof(BASE_TYPE)*CHAR_BIT > BUCKET_BITS};                                                                                          
      using CONTAINER = std::vector<BASE_TYPE>;                                                                                                                                              
      constexpr BASE_TYPE MAX{0xFF}; // 2**8-1 == 255                                                                                                                                        
      constexpr BASE_TYPE hi_bit_set = BASE_TYPE(1) << (BUCKET_BITS - 1); // 0x80 or 0b10000000                                                                                              
}

我希望能够选择要使用的类型,例如:

  // selection
  using BASE_TYPE = _4bits::BASE_TYPE;
  using CONTAINER = _4bits::CONTAINER;
  constexpr auto MAX = _4bits::MAX;
  constexpr auto hi_bit_set = _4bits::hi_bit_set;                                                                                                                                            
  constexpr bool cannot_overflow = _4bits::LEFT_SHIFT_HI_BIT_DOES_NOT_OVERFLOW;```

但是在一个只是一堆函数包装器的类中:

class bigint_to_string {
    // selection                                                                                                                                                                           
    using BASE_TYPE = _4bits::BASE_TYPE;                                                                                                                                                   
    using CONTAINER = _4bits::CONTAINER;                                                                                                                                                   
    static constexpr decltype(_4bits::BUCKET_BITS) BUCKET_BITS = _4bits::BUCKET_BITS;                                                                                                      
    static constexpr auto MAX = _4bits::MAX;                                                                                                                                               
    static constexpr auto hi_bit_set = _4bits::hi_bit_set;                                                                                                                                 
    static constexpr bool cannot_overflow = _4bits::LEFT_SHIFT_HI_BIT_DOES_NOT_OVERFLOW;                                                                                                   

private: // the class is just a wrapper to a bunch of functions, I don't want to allow objects
    bigint_to_string(const bigint_to_string&) = delete;                                                                                                                                    
    bigint_to_string(bigint_to_string&&) = delete;                                                                                                                                         
    bigint_to_string& operator=(const bigint_to_string&) = delete;                                                                                                                         
    bigint_to_string& operator=(bigint_to_string&&) = delete;                                                                                                                              
    virtual ~bigint_to_string() = delete;                                                                                                                                                  

public: // access interface
    static std::string get_decimal(CONTAINER bigint)
    using CONTAINER = std::vector<BASE_TYPE>;

private: // internal helper methods
    static bool is_zero(CONTAINER& bigint);                                                                                                                                                                                             
    static void canonize(CONTAINER& bigint);
    static void divide_by_2(CONTAINER& bigint)
    static void multiply_by_2(CONTAINER& bigint)
    static int cmp(const CONTAINER& a, const CONTAINER& b)
    static void set_bit_at(CONTAINER& bigint, std::size_t index, bool set=true)
    static CONTAINER divide(CONTAINER& n, CONTAINER d)
};

我的一个想法是将命名空间转换为结构,并将其作为类型传递:

struct Types{};
struct _4bits : Types {...};
struct _8bits : Types {...};

template <Types>
class bigint_to_string {...};

但这行不通...我不想将这些选项中的每一个参数化为模板参数,然后为每个“包”创建“宏”等,我真的希望将它们放在命名空间中或结构,然后一次将其全部传递给类。可能吗?

标签: c++c++20

解决方案


推荐阅读