繁体   English   中英

使用std :: initializer_list时防止缩小转换

[英]Preventing narrowing conversion when using std::initializer_list

#include <iostream>

struct X {
    X(std::initializer_list<int> list) { std::cout << "list" << std::endl; }
    X(float f) { std::cout << "float" << std::endl; }
};

int main() {
    int x { 1.0f };
    X a(1);     // float (implicit conversion)
    X b{1};     // list
    X c(1.0f);  // float
    X d{1.0f};  // list (narrowing conversion) ARG!!!

    // warning: narrowing conversion of '1.0e+0f' from 'float' to 'int'
    // inside { } [-Wnarrowing]
}

有没有其他方法可以从重载列表中删除std::initializer_list (即,使非列表ctors更有利),而不是使用()-initialization,或者至少禁止缩小转换(除了将警告转换为错误)?

我使用的是使用GCC 4.8的http://coliru.stacked-crooked.com/编译器。

实际上,在括号列表初始化器中包含缩小转换的程序是不正确的 我不确定为什么编译器只是给你一个警告,但它肯定应该在这里发出一个错误(FWIW, Clang这样做 )。

另请注意,这也是一种缩小(因而非法)的转换:

int x { 1.0f }; // ERROR! Narrowing conversion required

根据C ++ 11标准的第8.5.4 / 3段:

列表初始化对象或类型T的引用定义如下:

- 如果T是聚合,则执行聚合初始化(8.5.1)。 [...]

- 否则,如果初始化列表没有元素[...]

- 否则,如果Tstd::initializer_list<E> ,[...]

- 否则,如果T是类类型,则考虑构造函数。 枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数。 如果转换任何参数需要缩小转换(见下文),则程序格式错误 [...]

更确切地说,标准只说在这种情况下需要“诊断”,并且警告是诊断,因此编译器的行为是符合的 - 但我相信发出错误将是更好的行为。

这看起来像编译器错误。 您应该收到错误而不是警告。 大括号初始化永远不应该隐含地缩小。

从标准(第8.5.4节)

 struct B { B(std::initializer_list<int>); }; B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor B b2 { 1, 2.0 }; // error: narrowing 

你可以用std::enable_if实现你想要的。

#include <iostream>
#include <type_traits>

struct X {
    template<typename T, typename = typename std::enable_if<std::is_same<T,int>::value>::type>
    X(std::initializer_list<T>) { std::cout << "list" << std::endl; }
    X(float) { std::cout << "float" << std::endl; }
};

int main() {
    X a(1);     // float (implicit conversion)
    X b{1};     // list
    X c(1.0f);  // float
    X d{1.0f};  // float (yay)
}

适用于g ++ 4.8和clang 3.2

您可以使用-Wno-c++11-narrowing来关闭错误:

这是一个示例测试程序:

#include <cstdint>

struct foo {
    int32_t a;
};

void foo(int64_t val) {
    struct foo A = { val };
}

使用clang ++ - 3.8编译只需-std=c++11 ,我们得到声明的错误:

在此输入图像描述

添加-Wno-c++11-narrowing ,金色沉默:-)

在此输入图像描述

当然,缩小的问题可能会在稍后回过头来咬你,但有时可能更容易将技术债务的痛苦推迟到以后。 ymmv :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM