【问题标题】:Avoid the most vexing parse避免最麻烦的解析
【发布时间】:2012-11-06 11:07:52
【问题描述】:

如何让编译器创建临时对象,在它们上使用默认构造函数而不定义函数?

struct B {};
template<class T> struct C {};

template<class T,class T1>
struct A
{
  A(const T& t,const T1& t1): m_t(t),m_t1(t1)
  {
    std::cout << __PRETTY_FUNCTION__ << "\n";
  }

  T m_t;
  T1 m_t1;
};


int main() {
  A< B , C<B> > a0( B() , C<B>() );   // Function definition
  A< B , C<B> > a1( B b , C<B> c );   // dito, *at least A(const T& t,const T1& t1) not called
}

【问题讨论】:

  • 使用更多的括号,比如(B()),或者在C++11中使用B{}
  • @R.MartinhoFernandes:为什么会有这样的评论? :(

标签: c++ most-vexing-parse


【解决方案1】:

您可以将其中一个参数包含在一组额外的括号中,以防止它被解析为函数声明:

A< B , C<B> > a0( (B()) , C<B>() );

或者更好的是,如果您可以访问 C++11 编译器,请使用大括号初始化:

A< B , C<B> > a0{ B() , C<B>() };

【讨论】:

  • 值得注意的是,如果类型也有 initializer_list 构造函数,则有时无法使用大括号初始化。
【解决方案2】:

两种方式:

  1. 通过赋值初始化:

    auto a0 = A<B, C<B>>(B(), C<B>());
    

    请注意,在 C++17 之前,这会更改语义,因为它要求该类型有一个可用的复制或移动构造函数(尽管这将被省略,因此生成的代码是相同的)。

  2. 在至少一个参数周围使用更多括号:

    A<B, C<B>> a0((B()), C<B>());
    

两者都有效。第二种方式可能不可读,“多余的”括号会让不熟悉这种行为的人感到惊讶。

【讨论】:

    【解决方案3】:
    A< B , C<B> > a0((B()), (C<B>()));
    //               ^   ^  ^      ^
    

    使用外括号,每个参数只能是表达式,不能是声明。

    您实际上只需要 一个 的参数是这种情况,以防止整行被解析为表达式。你可以选择哪一个,或者两者都做。

    不要忘记在代码旁边写注释,说明“额外”括号是有充分理由的,否则天知道有一天会有人出现并在“次要”VCS 提交中删除它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-18
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多