2017-06-28 119 views
0

从经验上看,C++总是比列表初始值设定项更喜欢列表初始值设定项。我的问题是如何强制一个类型的值初始化,它也支持直接列表初始化。下面是一个最小的非工作例如:C++ 11值初始值设定项vs列表初始值设定项

#include <initializer_list> 

using namespace std; 

struct foo { 
    foo(int) {} 
    foo(initializer_list<char>) {} 
}; 

struct bar { 
    foo f{256}; 
}; 

在这个例子中,我想f使用构造foo(int)而非foo(initializer_list<char>)进行初始化。然而,GCC和Clang都拒绝了代码,因为256对于char来说太大了,这意味着C++规范要求选择列表初始值设定项。明显地注释掉foo的第二个构造函数修复了这个问题。定义bar以便在字段f上使用值初始化的最简单方法是什么?理想情况下,我可以避免复制初始化f,因为在我的实例中没有复制构造函数。

更新

澄清:当然有可能在bar每一个构造函数中明确初始化f。但我的问题特别是关于成员初始化语法,因为在具有大量构造函数的情况下,最好只在一个地方初始化某些字段,而不是全部复制代码。

+0

写一个构造函数? –

+0

只要写'foo f(256);'。 –

+0

我想看看为什么'initializer_list '是'{256}'的可行构造函数的解释。基于编译器行为推断关于规范的东西也是不安全的。有时候多个编译器会得到相同的错误。 –

回答

3

只要你需要foo是非可复制/移动,你需要foo有一个initializer_list构造,可以用来代替构造函数,这是你的行为。因此,如果你想解决这个问题,你必须改变其中的一个事实。

如果根本无法更改foo的定义,那么就搞砸了。向任何拥有课堂的人投诉。

第二个事实是可能是最容易改变,但即使这样也不会没有后果:

struct il {}; 

struct foo { 
    foo(int) {} 
    foo(il, initializer_list<char>) {} 
}; 

这完全消除歧义的问题。 foo{256}将始终调用单个整数构造函数。但是,foo在技术上没有initializer_list构造函数;你,而不是必须使用的标签类型il与值的初始化列表来调用它:

foo f{il{}, {/*actual list*/}}; 

这需要更多的支撑,但目前还没有真正的选择。

注意,在C++ 17,保证省音让你这样做:

struct bar { 
    foo f = foo(256); 
}; 

不管foo是移动与否。

+0

有趣的是,即使明确删除了“foo”的拷贝构造函数,在'foo f = foo(256)'中也可以在C++ 17中工作。谢谢。 – user3188445

相关问题