(已知)VC12中的编译器错误?

时间:2014-01-10 12:31:24

标签: c++ visual-c++ visual-studio-2013 compiler-bug

当使用VC12(在Visual Studio 2013 RTM中) [1] 编译时,此程序导致崩溃(在所有构建配置中),实际上它不应该:

#include <string>

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

int main()
{
    foo();
}

我知道两个无声的错误代码错误 可能 相关:

老实说,我认为这些是不同的。有谁知道

  1. 此连接是否存在主动跟踪的错误
  2. 是否有解决方法(或导致此错误的情况的明确描述,因此我们可以在我们的代码库中查找/避免它)?

  3. [1] 使用C ++ Console Application'向导'创建一个空项目。为简单起见,请禁用预编译的标头并保留所有默认值:http://i.stack.imgur.com/rrrnV.png

2 个答案:

答案 0 :(得分:11)

当默认参数是初始化列表时,Visual Studio看起来只是关于它调用的构造函数。这段代码:

#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() ;
}

gccclang中生成此结果,请参见live here

test ()
test ()

Visual Studio产生此结果:

test ()
test (int)

并且代码为:

#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() ;
}

gccclang生成此结果,请看live here

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

Visual Studio产生此错误:

 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

更新

为了进行健全性检查,我回到了标准,以确保在这种差异的根源上没有一些奇怪的规则,或者可能是某些限制导致此代码格式错误。据我所知,这段代码不是格式错误的。第8.3.5节语法特别允许这样:

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

部分8.5 初始值设定项8.3.6 默认参数似乎不添加任何限制,但此缺陷报告994. braced-init-list as a default argument 和工作文件Wording for brace-initializers as default arguments明确指出它是有意的并概述了对标准所做的修改以允许它并且查看增量没有明显的限制。

答案 1 :(得分:8)

活跃的问题已在November发回。发布的示例代码是:

Compile and run following code in VS2013

#include <string>

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

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

该漏洞已得到微软的认可。

似乎没有在那里发布的解决方法。 修改变通办法很容易基于避免列表初始化程序语法:

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

或者只是过时的(如果你不介意引入重载):

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