起步

hana的核心部分有两个概念:tagconcept

tag

tag是为了统一异构类型,比如一系列的integral_constant<int,n>,虽然它们是不同的类型,但是在概念上它们是一致的,这时候我们用integral_constant_tag来表示它们。

tag只是为了区别类型,事实上,我们通常只声明它,而不用定义它。就像这样:

  1. struct xxx_tag;

xxx代表实际类型,添加了_tag后缀只是一种习惯作法。我们看到了tag只是作为不同的类型而存在,而且编译器通常会优化掉它。tag的主要作用是用来“标签分派”的。

Tag dispatching

tag分派其实就是为了获得在编译进行分支的能力,可类比于运行时的if。但是不能直接在编译时运用if来使代码分支,原因是编译器会检查每一个分支,编译时的分支是互斥的,也就是一个分支通过了,其它的分支肯定通不过(编译)。但编译器不管哪个分支都要检查,这就导致编译失败。

解决问题的最好办法是使用常量if,即if constexpr(...) ... else ...,但这需要c++17标准的支持。退一步的办法是使用sfinae,标准库提供了enable_ifvoid_t(c++17)用来简化SFINAE的使用。还有一个办法就是定义具有分支能力的元函数,再有一个办法就是tag dispatching了。它最旱可能使用于标准库的迭代器。

基本用法是,把不同的类型用于函数重载,比如:

  1. struct tag_a;
  2. struct tag_b;
  3. void foo(int a,tag_a)
  4. {
  5. //...
  6. }
  7. void foo(int b,tag_b)
  8. {
  9. //...
  10. }
  11. void foo(int a)
  12. {
  13. //tag is typeof tag_a or tag b;
  14. foo(a,tag);
  15. }

concept