命名空间 'std' 中没有名为 'begin' 的成员。

5

我在Windows上成功编译了一段应该是跨平台的代码。现在在Mac OS X上使用Xcode编译时,出现以下错误:

std::valarray<float> v(32);
...
std::sort(begin(v), end(v));            # Use of undeclared identifier 'begin'
std::sort(std::begin(v), std::end(v));  # No member named 'begin' in namespace 'std'
std::sort(std::valarray::begin(v), std::valarray::end(v));  # Idem, error as well

为什么会出现“命名空间 'std' 中没有成员名为 'begin'”的错误?

9
非成员函数 begin 是 C++11 的一个特性,在 XCode 中尝试启用它。 - TartanLlama
1
@Basj:刚测试时看到了这个:) 我确认在命令行中添加-std=c++11后,它可以编译成功。我很高兴没有在没有测试的情况下回答 :) - Jean-François Fabre
3
什么时候std=c++11将成为默认选项?现在已经2016年了,很多问题只能通过添加这个开关来解决!请加快进度! - Jean-François Fabre
@Jean-FrançoisFabre 我猜这是一些旧的XCode版本?我的意思是,不包括C++11不够用户友好,在Mac上更是显而易见。哈哈。 - Yakk - Adam Nevraumont
如果您正在查找其他解决方案,这里有一个关于映射的可能性。如果您的映射是数据成员,并且您正在尝试在标记为“const”的非静态类方法内访问它,则访问mymap[x]将导致编译时错误,因为如果x不存在,则mymap[x]将为x创建一个条目,因此它会修改被标记为“const”的函数中的数据成员,因此违反了规定。如果您知道x已经存在于mymap中,请使用mymap.at(x),或者使用map.find(x)。 - ppadhy
2个回答

6

std::begin是在C++11中引入的。请参考此答案了解如何在XCode 4.2中启用C++11(方言名称可能已经发生变化)。

或者,如果您无法使用C++11,请切换到std::vector并使用v.begin()


1
即使OP使用C++11,valarray也没有begin和end成员函数。 - NathanOliver
@NathanOliver: 继续你在被删除的帖子中的评论:<valarray> 被定义为为 valarray 提供 std::begin 的重载。 - Martin Bonner supports Monica
@NathanOliver:打开C++11就是让代码正常工作的全部所需。 - Martin Bonner supports Monica
@MartinBonner 实际上,我不能使用C++11,因为它需要OS 10.7 SDK。而且为了保持向后兼容性(我的软件需要它),我必须使用Base SDK = OS X 10.5。当我按照您的说明启用C++语言方言和C++标准库时,我会收到“clang错误,对于stdlib libc++(需要OS 10.7或更高版本)无效的部署目标” 。 - Basj
啊,那种情况下,要么切换到向量+ v.begin(),要么使用&v[0],(&v[0])+v.size()。我不确定valarray是否保证是连续的,但在实践中它会是。 - Martin Bonner supports Monica
显示剩余9条评论

2
您可能正在使用C++03模式进行编译。请查看如何将您的IDE设置为C++ 11模式。 XCode 4.2 turn on C++11 可能会有所帮助。 std::sort(std::valarray::begin(v), std::valarray::end(v)); -- 我认为标准并不要求这个一定能正常工作。如果 valarray 实现了静态成员或Koenig friend 操作符等,那么也许可以。 std::valarray 没有成员 begin/end。在C++03中唯一的迭代方法是使用 [] 或者使用指针。 valarray 是保证连续的。 所以您可以写成:
namespace notstd {
  // addressof taken from http://en.cppreference.com/w/cpp/memory/addressof
  template<class T>
  T* addressof(T& arg) {
    return reinterpret_cast<T*>(
           &const_cast<char&>(
              reinterpret_cast<const volatile char&>(arg)));
  }

  template<class T>
  T* begin( std::valarray<T>& v ) { return addressof(v[0]); }
  template<class T>
  T* end( std::valarray<T>& v ) { return begin(v)+v.size(); }
  template<class T>
  T const* begin( std::valarray<T> const& v ) { return addressof(v[0]); }
  template<class T>
  T const* end( std::valarray<T> const& v ) { return begin(v)+v.size(); }
}

并在您的valarray上使用notstd :: begin


“begin”和“end”保证在以下容器中出现:<array>、<deque>、<forward_list>、<list>、<map>、<regex>、<set>、<string>、<unordered_map>、<unordered_set>和<vector>。 - NathanOliver
1
@NathanOliver: ...还有<valarray>,这是我们感兴趣的! - Martin Bonner supports Monica
@MartinBonner,这是因为 valarray 没有 beginend 成员函数。将其包含进去是愚蠢的,因为你无法使用它。从看起来的情况来看,任何拥有 begin/end 的标准头文件都会把 begin/end 包含进去,这是一个合理的做法。 - NathanOliver
感谢@Yakk。在这种情况下,使用(带有地址of...的)此代码比用&v[0]替换begin更好吗? - Basj
真正的胜利在于end的定义(实际上,几乎不需要使用addressof——对于必须与任意类型一起工作的库代码的作者来说,这更为重要)。 - Martin Bonner supports Monica
@basj Martin已经拥有它了。 - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接