为什么有些类型不能使用统一的初始化语法?

abi*_*bir 5 c++ uniform-initialization c++11

在将我的一些C++ 98代码更新到C++ 11时,我发现统一初始化并不是那么统一.其中一些与不完整类型相关void,而其他与pod有关.例如,对于简单的可复制类型,当初始化涉及复制/移动构造函数时,统一初始化对于直接初始化或复制初始化都不起作用.

例如

template<class T>
T foo() { return T("Hello World");}
foo<void>();
foo<std::string>();
--------
template<class T>
T foo() { return T{"Hello World"};}
foo<void>();
foo<std::string>();
Run Code Online (Sandbox Code Playgroud)

虽然第一部分编译,但后半部分失败了 error: compound literal of non-object type 'void'

struct pod { int x;int y;};
pod p{1,2}; //ok pod p(1,2) is error as usual
pod p2(p);

struct foo
{
    foo(foo const& rhs) : p_(rhs.p_){}
    pod p_;
};
--------
struct pod { int x;int y;};
pod p{1,2}; 
pod p2{p};

struct foo
{
    foo(foo const& rhs) : p_{rhs.p_}{}
    pod p_;
};
Run Code Online (Sandbox Code Playgroud)

在这里,下半部分在复制构造失败error: cannot convert 'pod' to 'int' in initialization.虽然我认为,这个pod类在c ++ 11中是一个微不足道的类型(甚至可以是简单的可复制类型),但除了原始类型之外,问题仍然存在

注意:

而以下工作,

struct conv
{
    operator int()const { return 1;}
};
pod p{1,2};
pod p2{conv{}};
Run Code Online (Sandbox Code Playgroud)

这没有,

struct conv
{
    operator pod()const { return pod{1,2};}
};
pod p{1,2};
pod p2{conv{}};
Run Code Online (Sandbox Code Playgroud)

我还注意到C数组确实可以使用统一初始化,但不能使用复制/移动构造函数.但这可能是由于数组是一个没有复制/移动构造函数或赋值的聚合.虽然我不知道为什么在c ++ 11中不允许这些语法(特别是当它们是类成员时,隐式复制/移动就是这样).

那么,为什么我不能盲目地将所有C++ 98初始化改为C++ 11样式的统一初始化(好吧,除了具有初始化列表的类型!)?

我正在使用GCC 4.8.1

Pot*_*ter 5

"统一初始化"是一个非标准术语,在其提案阶段推广初始化列表功能时有点不幸使用.

不,你无法在任何地方使用它.根据我的经验,最好将其限制为

  • 聚合(没有构造函数; C++ 98已经允许这个,但C++ 11扩展了支持)
  • 序列(initializer_list)
  • return 通过值表达式调用非显式构造函数

盲目地改变一切并期待没有语义变化只是论证和新闻 - 做某事因为它是新的和不同的,而不是因为它是合适的.

至于通用编程,是的,很难正确支持跨越上述类别的情况.在http://isocpp.org上向留言板发布具体投诉,也许负责该语言的人将更加努力地恢复"统一初始化"应该改进的通用顺序,而不是加剧:v).