c++ - 使用 C++11 的 Clang 类型转换具有不明确的编译器行为

标签 c++ templates c++11 clang

考虑以下代码:

#include<iostream>
#include<vector>
using namespace std;
class Foo {
public:
  template< typename T> 
  operator vector< T >() const {
    return vector< T >();
  }

  template< typename T> 
  operator T() const {
    return T();
  }
};

int main () {
  Foo b;
  vector< int >  q = b;
  q = b;
}

使用以下两个命令之一使用 Clang 或 g++ 编译它:

g++ test.cpp
clang++ test.cpp

启用 C++11 功能,但是失败了:

g++ --std=c++0x test.cpp
clang++ --std=c++11 test.cpp

报错信息如下:

test.cpp:20:5: error: use of overloaded operator '=' is ambiguous (with operand types 'vector<int>' and 'Foo')
  q = b;
  ~ ^ ~
/usr/include/c++/4.6/bits/stl_vector.h:373:7: note: candidate function
      operator=(vector&& __x)
      ^
/usr/include/c++/4.6/bits/stl_vector.h:362:7: note: candidate function
      operator=(const vector& __x);
      ^
/usr/include/c++/4.6/bits/stl_vector.h:394:7: note: candidate function
      operator=(initializer_list<value_type> __l)
      ^
1 error generated.

我不清楚为什么它在没有 C++11 的情况下工作,而在 C++11 下却失败了。 Moveover,注意这一行

vector< int >  q = b; // In the main function, line 19

在主函数中不会引起错误。任何人都可以解释为什么它不起作用,以及如何使它与 C++11 一起工作?

最佳答案

这里没有编译器错误。你的代码在 C++11 中被破坏了,因为 C++11 为赋值运算符添加了更多转换构造函数和更多重载。

这就是当您创建一个可以转换为任何类型(使用模板化转换)的类型时所面临的风险。 Foo很高兴将自己转换为 initializer_list<int>作为 vector<int> .

原因

vector<int> q = b;

适用于 Clang 3.1,而

vector<int> q(b);

失败,第一个是复制初始化,它需要隐式转换为vector<int>其次是复制构造函数调用,而第二个是直接初始化,它执行显式 转换。隐式转换的候选集较小,因为构造函数标记为 explicit被删除,解决了歧义。

Clang 3.0 和 3.1 之间的区别可能是库合规性修复,它将额外的构造函数标记为 explicit ,而不是对编译器行为的更改。

关于c++ - 使用 C++11 的 Clang 类型转换具有不明确的编译器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13055503/

相关文章:

c++ - 如何修复此类模板错误?

c++ - 从 lambda 调用函数时的查找规则是什么?

java - eclipse Java : Template for the 'create field' quick fix suggestion?

c++ - 从基类指针集合中调用非虚拟成员函数?

c++ - 如何向 std::array 添加算术运算符?

c++ - 有没有办法将左值和右值列表分别转换为具有引用类型和完整类型的元组?

C++ setter 编码约定。输入变量名称应该是什么?

c++ - Linux TCP/IP 编程中的精确定时保持事件

c++ - Qt和脚本系统

c++ - boost asio async_read header 连接过早关闭