【问题标题】:ambiguous conversion for functional-style cast with complex<double>具有 complex<double> 的函数式转换的模棱两可的转换
【发布时间】:2015-11-19 15:57:33
【问题描述】:

我有一个 MVE 程序,它可以使用 g++-5.2.0 编译和运行,但不能使用 clang-602.0.53。该程序尝试将 lambda 表达式分配给兼容类型的类型别名。

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

这个程序在使用 g++-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)

但是产生了一个我看不懂也不知道在clang下如何修复的错误:

$ 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)

这个错误是什么意思,为什么这段代码不能编译?

【问题讨论】:

    标签: c++ lambda g++ clang c++14


    【解决方案1】:

    你写的时候:

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

    我们查看std::complex&lt;double&gt; 的有效构造函数并找到:

    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&lt;double&gt;complex&lt;float&gt; 都可以从两个ints 构造。两者都不比另一个更好,这就是clang抱怨“模糊转换”的原因。

    最简单的解决方案是删除不必要的{}s:

    return complex<double>(1,0);
    

    请注意,您不需要将参数命名为 _,您可以不为其提供名称。

    【讨论】:

    • 我由此推断{1, 0} 的类型是void,因为编译器抱怨voidcomplex&lt;double&gt; 的转换,对吗?
    • @Reb.Cabin 错误的关键部分是ambiguous。该表达式的类型无关紧要。
    • @Reb.Cabin 括号列表是语法元素而不是完全成熟的表达式,不能说它们具有类型。
    猜你喜欢
    • 2021-08-25
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多