zoukankan      html  css  js  c++  java
  • C++ decltype类型说明符

    1 基本语法

    decltype 类型说明符生成指定表达式的类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

    语法为:

    decltype( expression )

    编译器使用下列规则来确定expression 参数的类型。

    • 如果 expression 参数是标识符或类成员访问,则 decltype(expression) 是 expression 命名的实体的类型。如果不存在此类实体或 expression 参数命名一组重载函数,则编译器将生成错误消息。
    • 如果 expression 参数是对一个函数或一个重载运算符函数的调用,则 decltype(expression) 是函数的返回类型。将忽略重载运算符两边的括号。
    • 如果 expression 参数是右值,则 decltype(expression) 是 expression类型。如果 expression参数是左值,则 decltype(expression) 是对 左值引用 类型的expression

    给出如下示例代码: 

    int var;
    const int&& fx(); 
    struct A { double x; }
    const A* a = new A();
    语句类型注释
    decltype(fx()); const int && 对左值引用的const int
    decltype(var); int 变量 var 的类型
    decltype(a->x); double 成员访问的类型
    decltype((a->x)); const double& 内部括号导致语句作为表达式而不是成员访问计算。由于a声明为 const指针,因此类型是对const double的引用。

    2 decltype和引用

    如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。但是有些时候,一些表达式向decltype返回一个引用类型。一般来说,当这种情形发生时,意味着该表达式的结果对象能作为一条赋值语句的左值:

    // decltype的结果可以是引用类型
    int i = 42, *p = &i, &r = i;
    decltype(r + 0) b; // OK, 加法的结果是int,因此b是一个(未初始化)的int
    decltype(*p) c; // Error, c是int&, 必须初始化

    因为r是一个引用,因此decltype(r)的结果是引用类型,如果想让结果类型是r所指的类型,可以把r作为表达式的一部分,如r+0,显然这个表达式的结果将是一个具体的值而非一个引用。

    另一方面,如果表达式的内容是解引用操作,则decltype将得到引用类型。正如我们所熟悉的那样,解引用指针可以得到指针所指对象,而且还能给这个对象赋值,因此,decltype(*p)的结果类型是int&而非int

    3 decltypeauto

    如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const和引用在内):

    const int ci = 0, &cj = ci;
    decltype(ci) x = 0; // x的类型是const int
    decltype(cj) y = x; // y的类型是const int&,y绑定到变量x
    decltype(cj) z; // Error, z是一个引用,必须初始化
    • decltype的结果类型与表达式形式密切相关

    对于decltype所用的引用来说,如果变量名加上了一对括号,则得到的类型与不加括号时会有所不同。如果decltype使用的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或多层括号,编译器就会把它当成是一个表达式。

    decltype((i)) d; // Error, d是int&, 必须初始化
    decltype(i) e;   // OK, e是一个未初始化的int
    • 模板函数的返回类型 
    • 在 C++11 中,可以结合使用尾随返回类型上的 decltype 类型说明符和 auto 关键字来声明其返回类型依赖于其模板参数类型的模板函数。
    • 在 C++14 中,可以使用不带尾随返回类型的 decltype(auto) 来声明其返回类型取决于其模板参数类型的模板函数。

    例如,定义一个求和模板函数:

    //C++11
     template<typename T, typename U>
    auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u)) 
            { return forward<T>(t) + forward<U>(u); };
    
    //C++14
    template<typename T, typename U>
    decltype(auto) myFunc(T&& t, U&& u) 
            { return forward<T>(t) + forward<U>(u); };

    forward:如果参数是右值或右值引用,则有条件地将其参数强制转换为右值引用。)

    附上一段源码:

    #include <iostream>
    #include <string>
    #include <utility>
    #include <iomanip>
    
    using namespace std;
    
    template<typename T1, typename T2>
    auto Plus(T1&& t1, T2&& t2) -> 
       decltype(forward<T1>(t1) + forward<T2>(t2))
    {
       return forward<T1>(t1) + forward<T2>(t2);
    }
    
    class X
    {
       friend X operator+(const X& x1, const X& x2)
       {
          return X(x1.m_data + x2.m_data);
       }
    
    public:
       X(int data) : m_data(data) {}
       int Dump() const { return m_data;}
    private:
       int m_data;
    };
    
    int main()
    {
       // Integer 
       int i = 4;
       cout << 
          "Plus(i, 9) = " << 
          Plus(i, 9) << endl;
    
       // Floating point
       float dx = 4.0;
       float dy = 9.5;
       cout <<   
          setprecision(3) << 
          "Plus(dx, dy) = " <<
          Plus(dx, dy) << endl;
    
       // String      
       string hello = "Hello, ";
       string world = "world!";
       cout << Plus(hello, world) << endl;
    
       // Custom type
       X x1(20);
       X x2(22);
       X x3 = Plus(x1, x2);
       cout << 
          "x3.Dump() = " << 
          x3.Dump() << endl;
    }

    运行结果为:

    Plus(i, 9) = 13
    Plus(dx, dy) = 13.5
    Hello, world!
    x3.Dump() = 42

     文章链接: http://blog.csdn.net/yhl_leo/article/details/50865552 

  • 相关阅读:
    JeePlus:代码生成器
    JeePlus:API工具
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1023 税收与补贴问题
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
    Java实现 洛谷 P1328 生活大爆炸版石头剪刀布
  • 原文地址:https://www.cnblogs.com/ye-ming/p/9304698.html
Copyright © 2011-2022 走看看