[c++11]跨平台字符串处理

这里的跨平台,指的是在windows linux android ios等主流操作系统,以及各自的编译器。

采用标准c++来处理,方法也是比较直接的。本文用代码来展示这一过程。字符串操作、正则表达操作,这里没展示,从API上看,是支持的。

本文所有代码,在debian linux strech和 windows10上编译通过。

字符串处理要用宿主OS的内部编码

比如windows:用wstring,就是utf16BE

linux,用u32string,就是utf32

继续阅读[c++11]跨平台字符串处理

[c++]模板特化与模板递归

Hello World

//比如计算斐波那契数列
template<int n>
struct Factorial{
	const static int value=Factorial<n-1>::value*n;
};
//特化终结递归,否则上面那个递归会死循环,编译时报错
template<>
struct Factorial<0>{
	const static int value=1;
};

遍历查找变长模板包中的类型

//再比如,查找Args...泛型参数的位置,
//这个例子很有意思,能把Args...一层一层拆解,很暴力,脱!!
template <int Index, class Search, class First, class... Types>
struct get_internal {
  typedef typename get_internal<Index + 1, Search, Types...>::type type;
  static constexpr int index = Index;
};

template <int Index, class Search, class... Types>
struct get_internal<Index, Search, Search, Types...> {
  typedef get_internal type;
  static constexpr int index = Index;
};

template <class T, class... Types> T get(std::tuple<Types...> tuple) {
  return std::get<get_internal<0, T, Types...>::type::index>(tuple);
}
继续阅读[c++]模板特化与模板递归

[RAAI]智能指针:scoped_ptr

#include <boost/scoped_ptr.hpp>
#include <iostream>

int main()
{
  boost::scoped_ptr<int> p{new int{1}};
  std::cout << *p << '\n';
  p.reset(new int{2});
  std::cout << *p.get() << '\n';
  p.reset();
  std::cout << std::boolalpha << static_cast<bool>(p) << '\n';
}

#include <boost/scoped_array.hpp>

int main()
{
  boost::scoped_array<int> p{new int[2]};
  *p.get() = 1;
  p[1] = 2;
  p.reset(new int[3]);
}

支持并发遍历、修改的map

问题

在游戏开发中,经常要存储大量对象,比如玩家、怪物,在增加、删除的同时,还需要遍历。在此,我们只讨论单线程并发,不考虑多线程。在多线程情况下处理这种情况,更是自找麻烦,况且效率低下。

  1. 删除、增加<=>遍历, 是矛盾的。遍历过程中新增、新删的对象,应该如何影响遍历?
  2. 遍历还有可能是并发的。如果使用了协程,这种情况出现的机率很高;就算不使用协程,还是有可能出现:那就是遍历嵌套,遍历vector的过程中,又开启了第二次遍历(有可能你调用了一个函数,这个函数启动了遍历)。
继续阅读支持并发遍历、修改的map

[c++]一边遍历一边删除

How to remove element while iterating?

使用标准模板库的时候,想过这个问题吗?可能有人说做不到,实际上时可以的。

      //q_是个普通的队列,我们检测到符合条件的元素,就删除它。
      for (auto one = q_.begin(); one != q_.end();) {
        if (!exists(one->first)) {
          one = q_.erase(one); //删除函数的返回值是关键
        } else {
          one++;
        }
      }

其实这里的关键就是erase方法的返回值,它返回的时下一个位置的iterator,如果到了末尾会返回end,注意,这里不需要++,因为已经时下一个了。

这样 ,我们一遍循环就完成了检测、删除,很高效。