类型萃取的初步探索

来源:互联网 发布:淘宝护肤品店铺简介 编辑:程序博客网 时间:2024/06/05 05:00

  • 问题引入
  • 一次尝试
  • 改进尝试
  • 有趣的东西


问题引入

最近在撸代码的时候突然遇到一个问题,观察以下代码:

void LexicalAnalyzerTest(char* filename);int main(int argc, char const *argv[]) {    LexicalAnalyzerTest(*++argv);    return 0;}

看到了吧,这样子会产生一个编译错误,无法将 char* 转换成 const char* 类型

于是我又开始作死

熟悉模板的人都应该知道 STL 有一个 type_traits 库,里面充斥着各种类型计算的模板,懂得人觉得也就那回事,略懂的人觉得卧槽好牛逼,不懂的人直叹这是 C++ 吗?

So,我想写一个模板,通过类型萃取将 char 萃取出来,然后带入函数

一次尝试

#include <iostream>#include <typeinfo>template <typename T>struct myTrait {    typedef T value;};template <typename T>struct myTrait<const T> {    typedef T value;};int main(int argc, char* argv[]){    if(typeid(char*) == typeid(myTrait<const char*>::value)) {        std::cout << "traited" << std::endl;    } else if (typeid(const char*) == typeid(myTrait<const char*>::value)) {        std::cout << "no trait" << std::endl;    }    return 0;}

恩,结果是,没有用

改进尝试

观察到了吗,原本是 char* const,而我写成了 const char*,那么修改一下:

#include <iostream>#include <typeinfo>template <typename T>struct myTrait {    typedef T value;};template <typename T>struct myTrait<const T> {    typedef T value;};int main(int argc, char* argv[]){    if(typeid(char*) == typeid(myTrait<char* const>::value)) {        std::cout << "traited" << std::endl;    } else if (typeid(const char*) == typeid(myTrait<char* const>::value)) {        std::cout << "no trait" << std::endl;    }    return 0;}

就有效果了

有趣的东西

我们来继续看一些有趣的东西,以下代码试图从 char*, char&, char const, const char, char* const, const char*, const char& 中萃取出类型 char

template <typename T>struct myTrait {    typedef T value;};int main(int argc, char* argv[]){    auto traited = [](){        std::cout << "traited" << std::endl;    };    auto noTrait = [](){        std::cout << "no trait" << std::endl;    };    std::cout << "traits char* to char:" << std::endl;    if(typeid(char) == typeid(myTrait<char*>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits char& to char:" << std::endl;    if(typeid(char) == typeid(myTrait<char&>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits char const to char:" << std::endl;    if(typeid(char) == typeid(myTrait<char const>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits const char to char:" << std::endl;    if(typeid(char) == typeid(myTrait<const char>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits char* const to char:" << std::endl;    if(typeid(char) == typeid(myTrait<char* const>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits const char* to char:" << std::endl;    if(typeid(char) == typeid(myTrait<const char*>::value)) {        traited();    } else {        noTrait();    }    std::cout << "traits const char& to char:" << std::endl;    if(typeid(char) == typeid(myTrait<const char&>::value)) {        traited();    } else {        noTrait();    }    return 0;}

没有一个模板特化,结果并非全都 noTrait,其中 char&, char const, const char, const char& 都成功萃取出类型 char,注意,这是在没有添加任何特化模板的情况下的到的结果

那么我们来添加一些模板,使得 char*, char* const, const char* 也能萃取出类型 char

template <typename T>struct myTrait<T*> {    typedef T value;};

添加以上特化模板后,char*const char* 都能萃取出类型 char

template <typename T>struct myTrait<const T*> {    typedef T value;};

以上模板只作用于 const char*

template <typename T>struct myTrait<T* const> {    typedef T value;};

以上模板只作用于 char* const

所以添加这两个模板就能萃取出某个类型的原始类型

以上就是简单的萃取,将类型萃取出来,然后再添加各种修饰,如果想了解更多可以去看 type_traits 中定义的内容

以上内容还涉及了 顶层 const底层 const 的概念,可以去学习一下


CSDN 辣鸡 MD 编辑器,无序列表格式全丢

原创粉丝点击