与列表初始化语法的自动分配混淆

时间:2014-08-15 18:17:50

标签: c++ c++11

我现在能够在我的工作中第一次使用C ++ 11,而且我可以随时学习。我已阅读GotW #94,并且在宣布局部变量而不是明确说明类型时,我尝试采用他的建议来使用auto

鉴于此,我有以下代码:

class foo
{
};

int main()
{
    auto f = foo const*{nullptr};
}

我在main中的作业无法编译并失败:

main.cpp: In function 'int main()':
main.cpp:13:18: error: expected primary-expression before 'const'
     auto f = foo const*{nullptr};
                  ^

我觉得我错过了一些明显的东西。我在这里做错了什么?

(我的样本是on coliru)。

2 个答案:

答案 0 :(得分:4)

使用函数表示法进行类型转换时,类型名称必须是简单类型说明符 typename-specifier §5.2.3 [expr.type.conv] ),基本上是指由单个单词组成的类型名称。

unsigned int a = unsigned int(42);

也失败了,并且没有涉及类型推断或列表初始化。

在我看来,在您的示例中使用auto相当于混淆。只需使用

foo const* f{nullptr};

如果必须使用auto,请创建别名

using foo_const_p = foo const*;
auto f = foo_const_p{nullptr};

答案 1 :(得分:1)

T(x)T{x}语法不允许将任意类型用于T。在某些情况下允许它会使语法相当复杂。如果确实想在这里使用auto,您需要包装类型,如下所示:

template <typename T> using id = T;
auto f = id<foo const*>{nullptr};

但就个人而言,我并不认为它在这里很有用。

更具体地说,C ++语法将语法结构定义为

postfix-expression:
  ...
  simple-type-specifier ( expression-listopt )
  ...
  simple-type-specifier braced-init-list
  ...

simple-type-specifier:
  ::opt nested-name-specifieropt type-name
  ::opt nested-name-specifier template simple-template-id
  char
  char16_t
  char32_t
  wchar_t
  bool
  short
  int
  long
  signed
  unsigned
  float
  double
  void
  auto
  decltype-specifier

type-name:
  class-name
  enum-name
  typedef-name
  simple-template-id

允许任意类型的语法是type-id规则的一部分,simple-type-specifier规则不是template-argument的选项之一,而是simple-template-id规则中{{1}}规则的可能性之一{{1}},这就是模板别名是有效解决方法的原因。