避免最烦恼的解析

时间:2012-11-06 11:07:53

标签: c++ most-vexing-parse

如何让编译器创建临时代码,在没有定义函数时使用默认构造函数?

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
}

3 个答案:

答案 0 :(得分:5)

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

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

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

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

答案 1 :(得分:5)

两种方式:

  1. 通过作业进行初始化:

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

    请注意,这会更改语义,因为它要求复制或移动构造函数可用于该类型(即使这样做会被省略,因此生成的代码也是相同的)。

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

    A<B, C<B>> a0((B()), C<B>());
    
  3. 要么有效。我更喜欢第二种方式,但它可能变得难以理解,“冗余”的括号会让那些不熟悉这种行为的人感到惊讶。

答案 2 :(得分:3)

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

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

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

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