auto decltype typeid std::is_same std::decay类型判断,返回值类型后置

中文标准库:类型支持(基本类型、RTTI、类型特性)

  • type_traits

中文标准库 该头文件里面包含了各种类型判断,例如:是否是某种基本数据类型,是否是某种类类型,是否是某种复合类型

  • typeinfo

中文标准库 该头文件定义了三个类,可以配合typeid使用

  • typeindex

中文标准库

  • limits 数值极限

中文标准库

  • std::decay:退化类型的修饰(如const& int退化为int)

注意:auto 返回值会有参数被decay(类型退化)的问题

转载:C++11的模板类型判断——std::is_same和std::decay

std::remove_const std::remove_cv等

C++四种类型转换

一、类型判断

1. 标准库中所有和类型有关的内容

中文标准库:type(包含:类型识别,类型修改,类型比较等)

std::is_const、std::is_volatile(上面的链接中这些都有)

2. 类型判断用来判断函数模板的类型

#include <iostream>
#include <type_traits> //is_same
//#include <typeinfo>  //typeid不需要包含此头文件,typeid是C++关键字

auto fun()
{
    std::string str = "string";
    return str;
}

int main()
{
    decltype(fun()) str1;  //decltype比较适合用来推断表达式的值的类型或函数返回值的类型

    int n = 0;
    decltype(n) n1;

    auto a = 99.99;
    decltype(a) b;

    std::cout << "str type:" << typeid(fun()).name() << std::endl;
    std::cout << "str2 type:" << typeid(str1).name() << std::endl;
    std::cout << "n type:" << typeid(n1).name() << std::endl;
    std::cout << "a type:" << typeid(a).name() << std::endl;
    std::cout << "b type:" << typeid(b).name() << std::endl;

    std::cout << "==========" << std::endl;

    if (std::is_same<decltype(std::string()), decltype(fun())>::value)
    {
        std::cout << "fun()的返回值类型和std::string相同" << std::endl;
    }
    if (typeid(a) == typeid(b))
    {
        std::cout << "a和b的类型相同" << std::endl;
    }

    return 0;
}

std::decval

decltype还有一定的局限性,例如不能获取没有构造函数的成员函数返回值类型。此时std::declval可以很好地解决该问题。

std::decval用来将任意类型T转换成引用类型,令在 decltype 表达式中不必经过构造函数就能使用成员函数。通常在模板中使用declval,模板接受的模板实参通常可能无构造函数,但有同一成员函数,均返回所需类型。

注意, declval 只能用于不求值语境,且不要求有定义;求值包含此函数的表达式是错误。通常,若odr使用此函数被则程序为病式。

std::invoke_result获取调用函数的返回值的类型

std::is_invocable在编译期间判断函数与传递参数是否匹配

二、返回值类型后置语法

1. 示例1:

template<class T, class U>
auto mul(T x, U y) -> decltype(x*y)  //->type返回值类型后置语法
{
    return x*y;
}

2. 示例2:

struct List 
{
    struct Link { /* ... */ };
    Link* erase(Link* p);	// 移除p并返回p之前的链接
    // ...
};

List::Link* List::erase(Link* p) { /* ... */ }  //第一个List::是必需的,这仅是因为List的作用域直到第二个List::才有效。

auto List::erase(Link* p) -> Link* { /* ... */ }//更好的表示方法
posted @ 2020-11-27 09:51  滴哒哒哒  阅读(180)  评论(0编辑  收藏  举报