Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid the most vexing parse

How do I get the compiler to create temporaries, use the default constructor on them while not defining a function?

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
}
like image 644
ritter Avatar asked Nov 06 '12 11:11

ritter


2 Answers

You can wrap one of your arguments in an extra set of parentheses to stop it from being parsed as a function declaration:

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

Or even better, if you have access to a C++11 compiler, use brace initialization:

A< B , C<B> > a0{ B() , C<B>() };
like image 152
Joseph Mansfield Avatar answered Sep 20 '22 00:09

Joseph Mansfield


Two ways:

  1. Initialise via assignment:

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

    Note that before C++17 this changes the semantics since it requires that a copy or move constructor is available for the type (even though that will be elided so the generated code is the same).

  2. Use more parentheses around at least one argument:

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

Either works. The second way might be unreadable and the “redundant” parentheses will surprise people not familiar with this behaviour.

like image 41
Konrad Rudolph Avatar answered Sep 22 '22 00:09

Konrad Rudolph