强制缩小转换警告
Force narrowing conversion warning
考虑以下说明一些缩小转换的代码:
template <class T>
class wrapper
{
template <class> friend class wrapper;
public:
constexpr wrapper(T value)
: _data(value)
{}
template <class U>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
wrapper& operator=(T value)
{_data = value; return *this;}
template <class U>
wrapper& operator=(wrapper<U> other)
{_data = other._data; return *this;}
private:
T _data;
};
int main(int argc, char* argv[])
{
wrapper<unsigned char> wrapper1 = 5U;
wrapper<unsigned char> wrapper2{5U};
wrapper<unsigned char> wrapper3(5U);
wrapper<unsigned int> wrapper4 = 5U;
wrapper<unsigned int> wrapper5{5U};
wrapper<unsigned int> wrapper6(5U);
wrapper<unsigned char> wrapper7 = wrapper4; // Narrowing
wrapper<unsigned char> wrapper8{wrapper5}; // Narrowing
wrapper<unsigned char> wrapper9(wrapper6); // Narrowing
wrapper7 = wrapper4; // Narrowing
wrapper8 = wrapper5; // Narrowing
wrapper9 = wrapper6; // Narrowing
return 0;
}
如何修改wrapper
成员的body,使其触发收缩转换的编译器警告?我的目标是让用户意识到他们的代码可能存在问题。
您可以使用统一的初始化语法触发缩小转换警告:
class wrapper
{
template <class> friend class wrapper;
public:
constexpr wrapper(T value)
: _data{value}
{}
template <class U>
constexpr wrapper(wrapper<U> other)
: _data{other._data} // note the curly brackets here
{}
wrapper& operator=(T value)
{_data = value; return *this;}
template <class U>
wrapper& operator=(wrapper<U> other)
{_data = {other._data}; return *this;} // and here
private:
T _data;
};
和
wrapper<unsigned int> wrapper1 = 5U;
wrapper<unsigned char> wrapper2 = wrapper1; // Narrowing
wrapper<unsigned char> wrapper3(wrapper1); // Narrowing
wrapper<unsigned char> wrapper4{wrapper1}; // Narrowing
wrapper2 = wrapper1; // Narrowing
我推荐一种不同的方式。您不需要弄乱您的代码。使用 g++ 编译时,添加 -Wconversion 标志。
要在缩小调用中停止编译,您可以在
上使用 SFINAE
template <class U>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
并将其更改为
template <class U, typename std::enable_if<sizeof(T) >= sizeof(U)>::type* = nullptr>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
如果您从中复制的基础类型的大小大于您正在初始化的对象的基础类型,这将停止编译。
考虑以下说明一些缩小转换的代码:
template <class T>
class wrapper
{
template <class> friend class wrapper;
public:
constexpr wrapper(T value)
: _data(value)
{}
template <class U>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
wrapper& operator=(T value)
{_data = value; return *this;}
template <class U>
wrapper& operator=(wrapper<U> other)
{_data = other._data; return *this;}
private:
T _data;
};
int main(int argc, char* argv[])
{
wrapper<unsigned char> wrapper1 = 5U;
wrapper<unsigned char> wrapper2{5U};
wrapper<unsigned char> wrapper3(5U);
wrapper<unsigned int> wrapper4 = 5U;
wrapper<unsigned int> wrapper5{5U};
wrapper<unsigned int> wrapper6(5U);
wrapper<unsigned char> wrapper7 = wrapper4; // Narrowing
wrapper<unsigned char> wrapper8{wrapper5}; // Narrowing
wrapper<unsigned char> wrapper9(wrapper6); // Narrowing
wrapper7 = wrapper4; // Narrowing
wrapper8 = wrapper5; // Narrowing
wrapper9 = wrapper6; // Narrowing
return 0;
}
如何修改wrapper
成员的body,使其触发收缩转换的编译器警告?我的目标是让用户意识到他们的代码可能存在问题。
您可以使用统一的初始化语法触发缩小转换警告:
class wrapper
{
template <class> friend class wrapper;
public:
constexpr wrapper(T value)
: _data{value}
{}
template <class U>
constexpr wrapper(wrapper<U> other)
: _data{other._data} // note the curly brackets here
{}
wrapper& operator=(T value)
{_data = value; return *this;}
template <class U>
wrapper& operator=(wrapper<U> other)
{_data = {other._data}; return *this;} // and here
private:
T _data;
};
和
wrapper<unsigned int> wrapper1 = 5U;
wrapper<unsigned char> wrapper2 = wrapper1; // Narrowing
wrapper<unsigned char> wrapper3(wrapper1); // Narrowing
wrapper<unsigned char> wrapper4{wrapper1}; // Narrowing
wrapper2 = wrapper1; // Narrowing
我推荐一种不同的方式。您不需要弄乱您的代码。使用 g++ 编译时,添加 -Wconversion 标志。
要在缩小调用中停止编译,您可以在
上使用 SFINAEtemplate <class U>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
并将其更改为
template <class U, typename std::enable_if<sizeof(T) >= sizeof(U)>::type* = nullptr>
constexpr wrapper(wrapper<U> other)
: _data(other._data)
{}
如果您从中复制的基础类型的大小大于您正在初始化的对象的基础类型,这将停止编译。