Эта программа, когда скомпилирована с VC12 (в Visual Studio 2013 RTM)[1] приводит к падению (во всех конфигурациях сборки), когда на самом деле это не должно:
#include <string>
void foo(std::string const& oops = {})
{
}
int main()
{
foo();
}
Я знаю о двух тихих плохих ошибках в коде может быть связаны:
Честно говоря, я думаю, что они разные, хотя. Кто-нибудь знает
[1] Просто создайте пустой проект с помощью «мастера» Консольного приложения C ++. Для простоты отключите предварительно скомпилированные заголовки и оставьте все значения по умолчанию: http://i.stack.imgur.com/rrrnV.png
Активная проблема была опубликована в ноябрь. Отправленный пример кода:
Compile and run following code in VS2013
#include <string>
void f(std::string s = {}) {
}
int main(int argc, char* argv[]) {
f();
return 0;
}
Ошибка была подтверждена Microsoft.
Похоже, что там нет обходного пути. редактировать Обходные пути могут быть легко основаны на том, чтобы избежать синтаксиса list-initializer:
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()); }
Это выглядит как 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() ;
}
производит этот результат в gcc
а также clang
, видеть это живи здесь:
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() ;
}
gcc
а также clang
произвести этот результат увидеть это живи здесь:
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 в качестве аргумента по умолчанию и рабочий документ Формулировка скобочных инициализаторов в качестве аргументов по умолчанию дать понять, что это было задумано, и обрисовать в общих чертах изменения, внесенные в стандарт, и, глядя на дельты, нет никаких очевидных ограничений.