1

考虑以下代码:

#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 的情况下工作,而它却失败了。移动,注意线

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

在 main 函数中不会导致错误。谁能解释为什么它不起作用,以及如何使它与 C++11 一起工作?

4

1 回答 1

2

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

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

原因是

vector<int> q = b;

在 Clang 3.1 中工作,而

vector<int> q(b);

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

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

于 2012-10-24T21:37:19.167 回答