2016-10-12 39 views
2

考虑下面的代码说明了一些收缩转换:队缩小转换警告

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成员的身体,使其触发器缩小转换的编译器警告?我的目标是让用户意识到他们的代码可能存在错误。

+4

缩小在哪里?您正在从7,8和9中的相同类型中复制初始化。 – NathanOliver

+0

有趣的是,有'Wnarrowing',但它似乎没有做任何事情。在这种情况下缩小错误似乎更容易。 – krzaq

+0

@NathanOliver谢谢,问题已纠正。 – Vincent

回答

5

可以触发收缩转换警告与统一初始化语法:

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 

任何最后四线will produce a narrowing conversion warning in g++, and compilation errors from the narrowing conversions in clang.

0

的我建议你用不同的方式。你不需要弄糟你的代码。当你使用g ++编译时,添加-Wconversion标志。

+0

问题的一部分是OP的模板部分地将警告短路。 – user4581301

3

要在狭窄呼叫可以使用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) 
{} 

Live Example

此停止编译,如果将停止编译的大小您正在复制的基础类型大于您正在初始化的对象的基础类型。