类型转换、显式构造函数等

Type conversion, explicit constructors etc

本文关键字:构造函数 类型转换      更新时间:2023-10-16

我有BigNum类。我到底需要实现什么方法、构造函数等才能达到预期效果(比如在评论中)?

class BigNum {
    //...?
};
BigNum a = 1; // compiles
a = 42; // compiles
BigNum b = 1L; // compiles
BigNum c = 1U; // compiles
BigNum d = 1UL; // compiles
BigNum e = true; // doesn't compile
BigNum f = '1'; // doesn't compile
BigNum a = 1; //compiles
BigNum b = 1L; //compiles
BigNum c = 1U; //compiles
BigNum d = 1UL; //compiles
BigNum e = true; //doesn't compile
BigNum f = '1'; //doesn't compile

对于这些,您需要非显式构造函数,它们将接受除boolchar之外的积分类型。您可以编写一套完整的积分重载,比如std::to_string。请注意,对于小于int的类型,您不需要重载,因为它们可以毫无歧义地升级为intunsigned int。您可以将所有这些调用委托给long longunsigned long long版本,并且只实现这两个版本。

// remember to define these
BigNum(unsigned long long x);
BigNum(long long x);
BigNum(unsigned long x);
BigNum(long x);
BigNum(unsigned int x);
BigNum(int x);

要禁用boolchar,可以删除这些构造函数。然后,对于那些您想要错误的行,将出现错误。如果你不这样做,他们只会被提升到int,这样就不会出现错误。

BigNum(bool x) = delete;
BigNum(char x) = delete;
// you might also want to delete these:
// BigNum(char16_t x) = delete;
// BigNum(char32_t x) = delete;

另一种方法是定义一个接受任何整型的构造函数模板,然后像以前一样为boolchar定义额外的已删除重载。这避免了必须编写多个实现。

template <typename Integral, typename = std::enable_if_t<std::is_integral<Integral>::value>>
BigNum(Integral i);
BigNum(bool b) = delete;
BigNum(char c) = delete;
a = 42; //compiles

为此,您需要赋值运算符。你可能只是想在这里玩同样的游戏。

// remember to define these
BigNum& operator=(unsigned long long x);
BigNum& operator=(long long x);
// you can delegate these to the above
BigNum& operator=(unsigned long x);
BigNum& operator=(long x);
BigNum& operator=(unsigned int x);
BigNum& operator=(int x);
BigNum& operator=(bool x) = delete;
BigNum& operator=(char x) = delete;
// BigNum& operator=(char16_t x) = delete;
// BigNum& operator=(char32_t x) = delete;

实际上并不那么简单,因为boolchar将隐式转换为其他积分类型。但我做了这个:

class BigNum {
public:
    template <
        typename T,
        typename = typename std::enable_if<std::is_integral<T>::value &&
            !std::is_same<T, bool>::value && !std::is_same<T, char>::value>::type>
    BigNum(T) {}
};

我建议使用模板和std::static_assert

struct BigNum {
    template <typename Int> BigNum(Int val)
    {
        std::static_assert(std::is_integral<Int>::value,"must be integral");
        std::static_assert(!std::is_same<Int,bool>::value,"can not be bool");
        std::static_assert(!std::is_same<Int,char>::value,"can not be char");
        // ...
    }
};

您可以对operator=进行类似的操作。

给定此

a = 42; //compiles

您还需要一个赋值运算符。简单示例:

BigNum& operator=(const int n)
{
    // relevant stuff here...
    return *this;
}