The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a template function whose return type depends on the types of its template arguments. Or,use auto and decltype to declare a template function that wraps a call to another function, and then returns the return type of the wrapped function.

The compiler uses the following rules to determine the type of the expression parameter:

(1)、If the expression parameter is an identifier or a class member access, decltype(expression) is the type of the entity named by expression. If there is no such entity or the expression parameter names a set of overloaded functions,the compiler yields an error message.

(2)、If the expression parameter is a call to a function or an overloaded operator function, decltype(expression) is the return type of the function. Parentheses around an overloaded operator are ignored.

(3)、If the expression parameter is an rvalue, decltype(expression) is the type of expression. If the expression parameter is an lvalue, decltype(expression) is an lvalue reference to the type of expression.

decltype is useful when declaring types that are difficult or impossible to declare using standard notation, like lambda-related types or types that depend on template parameters.

decltype is a standard C++11 feature. It is an "operator" which takes an expression and returns a type.

decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。

decltype关键字用于查询表达式的类型,并不会对表达式进行求值。decltype的作用是获得一个变量或表达式的类型。decltype 不会执行表达式而auto会,decltype仅仅推论一下表达式的类型。

对于decltype( e )而言,其判别结果受以下条件的影响:

(1)、如果e是一个标识符或者类成员的访问表达式,则decltype(e)就是e所代表的实体的类型。如果没有这种类型或者e是一个重载函数集,那么程序是错误的;

(2)、如果e是一个函数调用或者一个重载操作符调用(忽略e外面的括号),那么decltype(e)就是该函数的返回类型;

(3)、如果e不属于以上所述的情况,则假设e的类型是 T:当e是一个左值时,decltype(e)就是T&;否则(e是一个右值),decltype(e)是T。

auto是为所有人准备的,而decltype是提供给模板开发者的。

在C++中,decltype作为操作符,用于查询表达式的数据类型。decltype在C++11标准制定时引入,主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以表示的问题。

下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "decltype.hpp"
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>

//////////////////////////////////////////////
// reference: http://en.cppreference.com/w/cpp/language/decltype
struct A { double x; };
const A* a = new A{ 0 };

decltype(a->x) y;       // type of y is double (declared type)
decltype((a->x)) z = y; // type of z is const double& (lvalue expression)

template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u); // return type depends on template parameters

int test_decltype1()
{
	int i = 33;
	decltype(i) j = i * 2;

	std::cout << "i = " << i << ", " << "j = " << j << '\n';

	auto f = [](int a, int b) -> int
	{
		return a * b;
	};

	decltype(f) g = f; // the type of a lambda function is unique and unnamed
	i = f(2, 2);
	j = g(3, 3);

	std::cout << "i = " << i << ", " << "j = " << j << '\n';

	return 0;
}

///////////////////////////////////////////////////////////
// reference: https://msdn.microsoft.com/zh-cn/library/dd537655.aspx
template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
decltype(std::forward<T1>(t1) +std::forward<T2>(t2))
{
	return std::forward<T1>(t1) +std::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 test_decltype2()
{
	// Integer
	int i = 4;
	std::cout << "Plus(i, 9) = " << Plus(i, 9) << std::endl;

	// Floating point
	float dx = 4.0;
	float dy = 9.5;
	std::cout << std::setprecision(3) << "Plus(dx, dy) = " << Plus(dx, dy) << std::endl;

	// String
	std::string hello = "Hello, ";
	std::string world = "world!";
	std::cout << Plus(hello, world) << std::endl;

	// Custom type
	X x1(20);
	X x2(22);
	X x3 = Plus(x1, x2);
	std::cout << "x3.Dump() = " << x3.Dump() << std::endl;

	return 0;
}

///////////////////////////////////////////////////
// reference: http://thbecker.net/articles/auto_and_decltype/section_06.html
struct S {
	S(){ m_x = 42; }
	int m_x;
};

int x;
const int cx = 42;
const int& crx = x;
const S* p = new S();

// x is declared as an int: x_type is int.
typedef decltype(x) x_type;

// auto also deduces the type as int: a_ is an int.
auto a_ = x;

// cx is declared as const int: cx_type is const int.
typedef decltype(cx) cx_type;

// auto drops the const qualifier: b is int.
auto b = cx;

// crx is declared as const int&: crx_type is const int&.
typedef decltype(crx) crx_type;

// auto drops the reference and the const qualifier: c is an int.
auto c = crx;

// S::m_x is declared as int: m_x_type is int
// Note that p->m_x cannot be assigned to. It is effectively
// constant because p is a pointer to const. But decltype goes
// by the declared type, which is int.
typedef decltype(p->m_x) m_x_type;

// auto sees that p->m_x is const, but it drops the const
// qualifier. Therefore, d is an int.
auto d = p->m_x;

GitHubhttps://github.com/fengbingchun/Messy_Test

C++11中decltype的使用的更多相关文章

  1. c++11 之 decltype

    在C++中,decltype作为操作符,用于查询表达式的数据类型.decltype在C++11标准制定时引入,主要是为泛型编程而设计,以解决泛型编程中,由于有些类型由模板参数决定,而难以(甚至不可能) ...

  2. C++11 中值得关注的几大变化(网摘)

    C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 ...

  3. C++11 中值得关注的几大变化(详解)

    源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 (and Why You Should Care),赖勇浩做了一个中文翻译在这里. ...

  4. c++11——auto,decltype类型推导

    c++11中引入了auto和decltype关键字实现类型推导,通过这两个关键字不仅能够方便的获取复杂的类型,而且还能简化书写,提高编码效率.     auto和decltype的类型推导都是编译器在 ...

  5. c++11 中的注意事项

    1. C++11标准中让类的析构函数默认也是noexcept(true)的. 但如果显式地为析构函数指定了noexcept,或者类的基类或成员有noexcept(false)的析构函数,析构函数就不会 ...

  6. C++11的decltype关键字

    C++11的decltype关键字 概述 decltype关键字和auto有异曲同工之处 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了 ...

  7. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  8. C++ 11 中的右值引用

    C++ 11 中的右值引用 右值引用的功能 首先,我并不介绍什么是右值引用,而是以一个例子里来介绍一下右值引用的功能: #include <iostream>    #include &l ...

  9. IOS中的Block与C++11中的lambda

    ios中的block 可以说是一种函数指针,但更确切的讲,其实际上其应该算是object-c对C++11中lambda的支持或者说是一个语言上的变体,其实际内容是一样的,C++的lambda我已经有简 ...

随机推荐

  1. Android 高级UI设计笔记09:Android实现无限滚动列表

    1. 无限滚动列表应用场景: ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们 ...

  2. 2016 ACM/ICPC亚洲区大连站 F - Detachment 【维护前缀积、前缀和、二分搜索优化】

    F - Detachment In a highly developed alien society, the habitats are almost infinite dimensional spa ...

  3. Notepad++正则表达式使用

    推荐个正则表达式在线测试的工具http://ccmpp.com/Regex/ Notepad++正则表达式使用 -- ::| 分类: 文档 | 标签:正则表达式 替换 notepad++ 匹配 查找 ...

  4. sql server 中数据库数据导入到另一个库中

    这篇说了sql语句对于备份的数据库进行还原 ,如果数据量大了还是什么问题,发现我的数据丢失了一些,头疼 sql server 备份还原 下面使用的的数据导入来解决这个问题,因为数据量比较大,导出来的脚 ...

  5. mobienet, shufflenet

    参考github上各位大神的代码 mobilenet和shufflenet,实现起来感觉还是各种问题. mobilenet目前使用的代码来自这里:https://github.com/BVLC/caf ...

  6. spring(二)-反射、动态代理

    主要是对上一篇文章中涉及到的点做补充,欢迎指正! 1.  java反射知识-Spring IOC 依赖注入 Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类:在运行时构造任意一个 ...

  7. springboot 整合dubbo 消费模块引入springboot 之后自动注入jdbc 模块导致启动报错问题

    方案一: 排除方法 pom文件直接将数据起步模块内排除数据源自动注入 jdbc jar <!--mybatis-plus 集成 --><!--mybitis--><dep ...

  8. Javafxml

    FXML入门教程 本部分教程包括两部分内容: 为什么使用FXML(基本介绍以及用FXML创建用户界面的好处): 使用FXML创建用户界面(通过创建简单登录应用来完成本教程部分). 1.1 为何使用FX ...

  9. Object C学习笔记20-结构体(转)

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  10. POJ 1066--Treasure Hunt(判断线段相交)

    Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7857   Accepted: 3247 Des ...