2015-08-25 2 views
3

У меня есть программа MVE, которая компилируется и запускается с g ++ - 5.2.0, но не с clang-602.0.53. Программа пытается присвоить лямбда-выражение псевдониму типа совместимого типа.неоднозначное преобразование для функционального стиля с комплексом <double>

#include<iostream> 
#include<complex> 

using std::cout; 
using std::endl; 
using std::complex; 
// type alias 
using CfDD = complex<double> (*) (double); 
// lambda of compatible type 
auto theLambda = [] (double _) {return complex<double>({1,0});}; 

int main() 
{ // Show that the lambda is callable: 
    cout << theLambda(3.14) << endl; 
    // Show that the lambda is assignable to a var of type CfDD 
    CfDD cfdd = theLambda; 
    cout << cfdd (3.14) << endl; 
} 

Эта программа работает при компиляции с г ++ - 5.2.0:

$ g++-5 --version 
g++-5 (Homebrew gcc 5.2.0) 5.2.0 
    ... 
$ g++-5 -std=c++14 main.cpp && ./a.out 
(1,0) 
(1,0) 

Но выдает ошибку, что я не понимаю и не знаю, как исправить под звоном:

$ gcc --version 
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with- gxx-include-dir=/usr/include/c++/4.2.1 
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) 
    ... 

$ gcc -std=c++14 main.cpp 

main.cpp:10:40: error: ambiguous conversion for functional-style cast from 'void' to 
    'complex<double>' 
auto theLambda = [] (double _) {return complex<double>({1,0});}; 
             ^~~~~~~~~~~~~~~~~~~~~ 
    ...  candidate is the implicit move constructor 
class _LIBCPP_TYPE_VIS_ONLY complex<double> 
          ^
    ...  candidate is the implicit copy constructor 
candidate constructor 
complex<double>::complex(const complex<float>& __c) 

Что означает эта ошибка и почему этот код не компилируется?

ответ

6

Когда Вы писали:

return complex<double>({1,0}); 

мы посмотрим на действующих конструкторами для std::complex<double> и найти:

constexpr complex(double re = 0.0, double im = 0.0); // (1) 

constexpr complex(const complex& other); // (2) 

constexpr complex(const complex<float>& other); // (3a) 
explicit constexpr complex(const complex<long double>& other); // (3b) 

Мы построения этого объекта со списком инициализатора. Таким образом, (1) не является жизнеспособным, и ни один из них не является (3b), так как этот конструктор помечен explicit. Остальные два, однако, жизнеспособны, так как оба complex<double> и complex<float> могут быть построены из двух int с. Ни один из них не лучше другого, поэтому кланг жалуется на «неоднозначное обращение».

Самое простое решение отказаться от ненужных {} сек:

return complex<double>(1,0); 

Обратите внимание, что вам не нужно назвать аргумент _, вы можете просто не указать имя для него.

+0

Я заключил, что тип '{1, 0}' недействителен, потому что компилятор жаловался на преобразование 'void' в' complex ', правильно? –

+1

@ Reb.Cabin Ключевая часть ошибки - «неоднозначная». Тип этого выражения не имеет значения. – Barry

+1

@ Reb.Cabin Скрепленные списки - это синтаксические элементы, а не полностью выраженные выражения, их нельзя назвать типом. –

Смежные вопросы