避免隐式转换

3

我正在开发一个项目,需要一个通用的C++封装器来处理大数库。如果该库提供了类似以下的C风格函数:

//assignment
lib_set(lib_type data, lib_type input);
lib_set_si(lib_type data, long input);
lib_set_ui(lib_type data, unsigned long input);

//addition
lib_add(lib_type data, lib_type input);
lib_add_ui(lib_type data, unsigned long input);

为了避免在不必要的情况下创建临时对象,我最终得到了像这样的代码:
class wrapper
{
private:
    lib_type data;
public:

    wrapper()
    {
        lib_set_ui(this->data, 0UL);
    }

    wrapper (const wrapper &input)
    {
        lib_set(this->data, input.data);
    }

    wrapper (const long input)
    {
        lib_set_si(this->data, input);
    }

    wrapper (const unsigned long input)
    {
        lib_set_ui(this->data, input);
    }

    wrapper &operator+= (const wrapper &input)
    {
        lib_add(this->data, input.data);
        return *this;
    }

    wrapper &operator+= (const unsigned long input)
    {
        lib_add_ui(this->data, input);
        return *this;
    }
};

不幸的是,如果我这样做:

wrapper x(2);
x += -2;

编译器(GCC / VS2010)甚至不会发出警告,提示我正在尝试将 int 显式转换为 unsigned long,这绝对不是我想要的结果...
所以,在这种情况下,如何为包装器类(wrapper class)重载运算符,使得在不需要创建临时 wrapper 对象时也能正常工作?如果我删除 wrapper &operator+= (const unsigned long input) 重载,则必须使用以下内容:
wrapper x(2);
x += wrapper(-2);
x += -2;//implicitly casts -2 to wrapper

但我认为我不能依赖于编译器可能能够优化掉额外的对象这一事实...


我猜你正在使用带有 const long 参数版本的这两个参数进行调用。可能甚至没有进行任何转换。 - user308323
哦,现在我正确地阅读了这个。编辑:天啊,我应该停止回答问题,我混淆了答案和评论。 - user308323
1
如果您为有符号整数 += 提供了重载,它是否能正常工作? - Jay
4
@MihaiTodor 只需要最大的类型(如 int64_t/uint64_t)或你的数据所需的最大类型即可。 - Andrei Tita
1
@MihaiTodor 嗯,由于推广规则的缘故,这有点复杂。你会很安全,但是根据所涉及的类型,你可能会遇到过载歧义(编译器错误),这将需要一些显式转换,这可能或可能不可接受在你的情况下。 - Andrei Tita
显示剩余11条评论
1个回答

3

我不知道有没有办法像你描述的那样禁止隐式转换。但是,至少可以让编译器发出警告。

如果你使用gnu Mingw/gcc,只需在编译时传递-Wconversion-Wsign-conversion即可。现在应该会收到有关上述代码的警告。

对于MSVC,/Wall/W4应该可以实现相同的功能。


+1 for -Wsign-conversion。我几乎确定它是由-Wall-Wextra启用的。你知道除了-Wall -Wextra -Wconversion -Wsign-conversion之外,还有哪些可爱的警告开关应该发送给编译器以确保安全吗?在Visual Studio中有没有实现相同功能的方法? - Mihai Todor
1
@MihaiTodor:默认情况下,Visual Studio 会警告有关符号转换的问题。如果没有,则可以进入项目设置,在其中将警告级别设置为更高级别(我认为默认值为3)。 - Mooing Duck
@MooingDuck 看来我得去/W4,但还是谢谢你指出来!这真的很有帮助。 - Mihai Todor
1
@MooingDuck 啊,这解释了很多问题 - 我忘记在测试随机代码的项目上启用 /W4。 - Andrei Tita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接