(Known) compiler bug in VC12?

旧巷老猫 提交于 2019-11-27 21:54:24

An active issue was posted back in November. The sample code posted was:

Compile and run following code in VS2013

#include <string>

void f(std::string s = {}) {
}

int main(int argc, char* argv[]) {
    f();
    return 0;
}

The bug has been acknowledged by Microsoft.

There doesn't seem to be a work-around posted there. Edit Workarounds can easily be based on avoiding the list-initializer syntax:

void f(std::string s = "");
void f(std::string s = std::string());
void f(std::string s = std::string {});

Or just the old-fashioned (if you don't mind introducing overloads):

void f(std::string s);
void f() { f(std::string()); }

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!