0
\$\begingroup\$

The context is a library to represent numbers (in this case integers) by wheighted position by radix powers for every radix R, passed as template argument. These derived types are digits of radix R, R_alphabet = {0,1,2,...,R-1}. The base class is to have holded the dig_t object as base_dig_t plus the radiz in the container for the number.

template<std::unsigned_integral Type>
struct base_dig_t;

template<   std::unsigned_integral Type,
            Type R
        >
// It does not add any data member to class
struct dig_t : public base_dig_t<Type>; 

template<std::unsigned_integral Type>
struct base_dig_t
{
    // default constructor
    constexpr 
    base_dig_t() 
    noexcept : 
        m_d(0) 
    {}
    
    // constructor by constant reference to 
    // wrapped arithmetic integral type
    constexpr 
    base_dig_t(const Type& t) 
    noexcept : 
        m_d(t) 
    {}
    // constructor by move the 
    // wrapped arithmetic integral type
    constexpr 
    base_dig_t(Type&& t) 
    noexcept : 
        m_d(std::move(t)) 
    {}
    
    // constructor by constant reference 
    // to derived type
    template<Type R>
    constexpr 
    base_dig_t(const dig_t<Type,R>& t) 
    noexcept : 
        m_d(t.base_dig_t::m_d) 
    {}
    // constructor by move the derived type
    template<Type R>
    constexpr 
    base_dig_t(dig_t<Type,R>&& t) 
    noexcept : 
        m_d(std::move(t.base_dig_t::m_d)) 
    {}
    
    // usual constructor by reference
    constexpr 
    base_dig_t(const base_dig_t&) 
    noexcept = default;
    // usual constructor by move
    constexpr 
    base_dig_t(const base_dig_t&&) 
    noexcept = default;
    
    // assignation operator by constant reference 
    // to wrapped arithmetic integral type
    constexpr 
    const base_dig_t & 
    operator= (const Type& t) 
    noexcept 
    {m_d = t; 
     return (*this);}
    // assignation operator by reference 
    // to wrapped arithmetic integral type
    constexpr 
    base_dig_t & 
    operator= (Type& t) 
    noexcept 
    {m_d = t; 
     return (*this);}
    // assignation operator by move 
    // wrapped arithmetic integral type
    constexpr 
    base_dig_t & 
    operator= (Type&& t) 
    noexcept     
    {m_d = std::move(t); 
     return (*this);}

    // assignation operator by constant reference 
    // to derived type
    template<Type R>
    constexpr 
    const base_dig_t & 
    operator= (const dig_t<Type,R>& t) 
    noexcept  
    {m_d = t.base_dig_t::m_d; 
     return (*this);}
    // assignation operator by reference to derived type
    template<Type R>
    constexpr 
    base_dig_t & 
    operator =(dig_t<Type,R>& t) 
    noexcept  
    {m_d = t.base_dig_t::m_d; 
     return (*this);}
    // assignation operator by move the derived type
    template<Type R>
    constexpr 
    base_dig_t & 
    operator =(dig_t<Type,R>&& t) 
    noexcept 
    {m_d = std::move(t.base_dig_t::m_d); 
     return (*this);}

    
    // usual assignation operator by constant reference
    constexpr 
    const base_dig_t & 
    operator= (const base_dig_t& d) 
    noexcept  
    {m_d = d.m_d; 
     return (*this);}
    // usual assignation operator by reference
    constexpr 
    base_dig_t & 
    operator=(base_dig_t&) 
    noexcept = default; 
    // usual assignation operator by move
    constexpr 
    base_dig_t & 
    operator= (base_dig_t&&) 
    noexcept = default;
    
    // several casts
    constexpr explicit 
    operator Type() const 
    noexcept
    {return m_d;}
    constexpr explicit 
    operator const Type&() const 
    noexcept 
    {return m_d;}
    constexpr explicit 
    operator Type&() 
    noexcept 
    {return m_d;}
    constexpr explicit 
    operator Type&&() 
    noexcept 
    {return std::move(m_d);}
    
protected:

    Type m_d;
    
};

// This template typename does not add 
// any data member to base class
template<   std::unsigned_integral Type,
            Type R
        >
struct dig_t : public base_dig_t<Type> 
{
    // Contructors from base_dig_t<Type>
    // Assignation operators for base_dig_t<Type>
    // this->base_dig_t::m_d = arg.base_dig_t::m_d%R;
    
    // Contructors from Type
    // Assignation operators for Type
    // this->base_dig_t::m_d = arg%R;

    // Proper constructors
    // Proper assignation operators
    
    // Explicit overload cast operators 
    // to return base_dig_t::m_d
    
    // Overload 
    // by template members functions
    // the arithmetic operators for
    // R-modular behavior   
    
}; 
\$\endgroup\$
2
  • \$\begingroup\$ To put your description in simpler terms, it's a bignum library - is that correct? \$\endgroup\$ Apr 22, 2022 at 12:19
  • \$\begingroup\$ But the library I code is with pedagogical target. One example is bignum, but numbers complement Radix format with fixed width and fixed radix. Or generalized IEEE-754. \$\endgroup\$
    – Earendil
    Apr 22, 2022 at 17:01

1 Answer 1

1
\$\begingroup\$

Not sure I like the style:

// several casts
constexpr explicit 
operator Type() const 
noexcept
{return m_d;}
constexpr explicit 
operator const Type&() const 
noexcept 
{return m_d;}
constexpr explicit 
operator Type&() 
noexcept 
{return m_d;}
constexpr explicit 
operator Type&&() 
noexcept 
{return std::move(m_d);}

Even one by itself:

constexpr explicit 
operator Type() const 
noexcept
{return m_d;}

Is hard to read and takes up a lot of vertical space. When you have a bunch it is unreadable:

I would align them like this so it becomes easy to see what changes between them.

// several casts
constexpr explicit operator       Type()   const noexcept  {return m_d;}
constexpr explicit operator const Type&()  const noexcept  {return m_d;}
constexpr explicit operator       Type&()        noexcept  {return m_d;}
constexpr explicit operator       Type&&()       noexcept  {return std::move(m_d);}

So now that I can read it.
You have a type that automatically converts itself to an R-Value reference. I am not sure if that is allowed or not; but it definitely makes my spidey senses go all funny. Would love to understand the use case of this.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.