NULL 和 0 行为相同的问题

问题描述

我正在上课:

#include <iostream>
#include <list>
using namespace std;

class Int{
    list <int64_t> data;
    bool sign;
public:
    Int(int64_t val = 0) : sign(false) {
        cout << "Int(int) called\n";
    }
    Int(const char* str): sign(false) {
        cout << "Int(const char* called)\n";
    }
};

int main(){
    Int a = "328739";     // line 1,ok
    Int a2 = "ehfjhs";    // line 2,ok
    Int a3 = 4338974;     // line 3,ok
    Int a4 = 0;    //line 4,Issue
    return 0;
}
@H_502_4@

一切正常,除了第 4 行。

一旦我执行 Int a4 = 0;@H_502_4@,构造函数 Int(const char* str)@H_502_4@ 就会被调用,因为 0@H_502_4@ 等价于 NULL@H_502_4@。但我希望改为调用 Int(int64_t val = 0)@H_502_4@。

我可以做的一个简单的修复是做 Int a4 = int(0);@H_502_4@,这在一边是可以的。但我想让它变得灵活,所以 0 只触发 Int(int64_t val = 0)@H_502_4@。

解决方法

作为另一个答案的替代方案,您可以创建一个接受任何整数类型的模板构造函数。这将解决歧义并额外适用于任何整数类型或文字。

#include <iostream>
#include <list>
using namespace std;

class Int{
    list <int64_t> data;
    bool sign;
public:
    template <typename T,std::enable_if_t<std::is_integral_v<T>>* = nullptr>
    Int(T val = 0) : sign(false) {
        cout << "Int(Integral) called\n";
    }
    Int(const char* str): sign(false) {
        cout << "Int(const char* called)\n";
    }
};

int main(){
    Int a = "328739";     // line 1,ok
    Int a2 = "ehfjhs";    // line 2,ok
    Int a3 = 4338974;     // line 3,ok
    Int a4 = 0;           // line 4,ok
    return 0;
}
,

这里的关键是 0 不是 int64_t,因此它必须经过隐式转换才能在您的任一构造函数中使用。两个构造函数在这里同样有效。 gcc 和 clang 实际上将歧义标记为错误,而不是像您遇到的那样随意选择。

0 的类型是 int,所以如果你有一个 int 构造函数,它会绑定到 0 而无需事先进行任何隐式转换,从而解决了歧义:

class Int{
    list <int64_t> data;
    bool sign;
public:
    Int(int64_t val = 0) : sign(false) {
        cout << "Int(int) called\n";
    }
    Int(int val) : sign(false) {
        cout << "Int(int) called\n";
    }
    Int(const char* str): sign(false) {
        cout << "Int(const char* called)\n";
    }
};