Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

This program, when compiled with VC12 (in Visual Studio 2013 RTM)[1] leads to a crash (in all build configurations), when really it shouldn't:

#include <string>

void foo(std::string const& oops = {})
{
}

int main()
{
    foo();
}

I know of two silent bad codegen bugs that might be related:

Honestly I think these are different, though. Does anyone know

  1. whether there is an actively tracked bug on connect for this
  2. whether there is a workaround (or an explicit description of the situation that causes this bug, so we can look for it/avoid it in our code base)?

[1] Just create an empty project using the C++ Console Application 'wizard'. For simplicity, disable precompiled headers and leave all defaults: http://i.stack.imgur.com/rrrnV.png

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
186 views
Welcome To Ask or Share your Answers For Others

1 Answer

It looks like Visual Studio is just broken with respect to which constructor it calls when the default argument is an initializer list. This code:

#include <iostream>

struct test {
  test ()  { std::cout << "test ()" << std::endl ; } 
  test (int)  { std::cout << "test (int)" << std::endl ; }
};

void func( test const &s = {} )
{
}

int main()
{
    test s = {} ;
    func() ;
}

produces this result in gcc and clang, see it live here:

test ()
test ()

while Visual Studio produces this result:

test ()
test (int)

and for this code:

#include <iostream>
#include <initializer_list>

struct test {
  test ()  { std::cout << "test ()" << std::endl ; };

  test (int)  { std::cout << "test (int)" << std::endl ; };
  test ( std::initializer_list<int>) { std::cout << "test (initializer_list<int>)" << std::endl ; } ;
};

void func( test const &s = {0} )
{
}

int main()
{
    test s = {0} ;
    func() ;
}

gcc and clang produce this result see it live here:

 test (initializer_list<int>)
 test (initializer_list<int>)

while Visual Studio produces this error:

 error C2440: 'default argument' : cannot convert from 'initializer-list' to 'const test &'
    Reason: cannot convert from 'initializer-list' to 'const test'
    No constructor could take the source type, or constructor overload resolution was ambiguous

Update

For a sanity check, I went back to the standard to make sure there wasn't some odd rule at the root of this difference or perhaps some restriction that makes this code ill-formed. As far as I can tell this code is not ill-formed. Section 8.3.5 grammar specifically allows this:

parameter-declaration:
  attribute-specifier-seqopt decl-specifier-seq declarator
  attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
  [...]

It does not seem like section 8.5 Initializers or 8.3.6 Default arguments add any restrictions but this defect report 994. braced-init-list as a default argument and working paper Wording for brace-initializers as default arguments make it clear that it was intended and outline the changes made to the standard to allow it and looking at the deltas there are no obvious restrictions.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...