hi, i am reading the book "The c++ standard library -- a tutorial and reference"{N.M.Josuttis}

in the beggining of the 6th chapter it says{in regard to container initialization}::

std::deque<int> c(
		(std::istream_iterator<int>(std::cin)),
                  (std::istream_iterator<int>())  
		  );

{the weird indentation is on purpose}

instead of::

std::deque<int> c(std::istream_iterator<int>(std::cin),
                  std::istream_iterator<int>());

because

In this case, c declares a function with a return type that is deque<int>. Its first
parameter is of type istream_iterator<int> with the name cin
{???}, and its second
unnamed parameter is of type "function taking no arguments returning
istream_iterator<int>." This construct is valid syntactically as either a declaration
or an expression. So, according to language rules, it is treated as a declaration. The extra
parentheses force the initializer not to match the syntax of a declaration.

so the question is how can the compiler think that this is function....since std::istream_iterator<int>(std::cin) is not a type.

Dani AI

Generated

This is the classic "most vexing parse": the grammar will interpret a token sequence as a declaration if that is a valid parse. That is why the compiler can treat the constructor-looking form as a function declaration even though std::istream_iterator<int>(std::cin) looks like a temporary expression. As noted, the tokens can be regrouped into a declaration; as showed with a simpler case, extra parentheses change whether the parser sees an expression or a declarator.

Practical ways to avoid the ambiguity (without repeating the book example): use C++11 list/braced initialization, or fill the container with algorithms instead of relying on the two-iterator constructor.

std::deque<int> c{ std::istream_iterator<int>(std::cin),
                   std::istream_iterator<int>() };

or

std::deque<int> c;
std::copy(std::istream_iterator<int>(std::cin),
          std::istream_iterator<int>(),
          std::back_inserter(c));

A short caution: braced initialization prevents the most vexing parse because braces cannot form a function-declaration, but it can change overload resolution when an initializer_list constructor is viable. For iterator-range construction this is usually not a problem, but it is worth checking overloads when switching to brace syntax.

Further reading: cppreference's discussion of the and list initialization give the formal background and practical rules.

Recommended Answers

All 3 Replies

>so the question is how can the compiler think that this is function
This is how it would be parsed:

deque<int> c ( istream_iterator<int> cin, istream_iterator<int> );

That looks exactly lot like a function declaration, doesn't it?

perhaps this would clarify (not different, but the types involved are simpler and therefore the example is easier to follow).

void foobar( int a, int b ) {}

int main()
{
  int a = 78 ;
  int foo( int(a) ) ; // is this the declaration (of a function foo)
                      // or the definition of an int foo?
  int(*pfn)(int) = &foo ; // it is a declaration!

  int bar( (int(a)) ) ; // can't be the declaration (of a function bar)
  int* pi = &bar ; // so, must be the definition of an int bar
  // reason (int(a)) is an expression because of parantheses; 

  // for example
  foobar( a, bar ) ; // ok
  // foobar( (a, bar) ) ; // error, too few arguments to function foobar
                       // because (a,bar) is *a single* expression
}

int foo( int(a) )
{
  return a+6 ;
}

there are several threads in comp.std.c++ which discuss why the language rules are framed this way, what would have been the alternatives etc. here is one of them http://groups.google.com/group/comp.std.c++/browse_thread/thread/57b52b0a1a40a9ad

commented: thanks for the example +1

thanks for your answers! vijayan your example example did clarify ...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.