奇妙的typename

将项目从VS2017转移到Linux下产生的诸多编译错误 前段时间把项目从windows挪到Linux下编译,过程中发现了许多问题,原本在VS下编译没问题的代码在gcc底下就大量报错,解决了很久,其中大部分是同事编码不规范的原因,剩下错误都是精华,今天特意整理了一下,重现一遍。本次编译GCC版本为7.3。 1. typedef/using changes meaning of ‘…’ from ‘…’ 这个问题的出在42行,编译器认为这个声明不正确,... 阅读详情

首先是一种解释:

 

1, 什么地方使用?用在模板定义里,标明其后的模板参数是类型参数。

    例如

 template<typename  T, typename Y>
T foo(const T& t, const Y& y){//....};

template<typename T>
class CTest
{
private:
 T t;
public:
 //...
}

    其实,这里最常用的是使用关键字class,而且二者功能完全相同,这里的class和定义类时的class完全是两回事,C++当时就是为了减少关键字,才使用了class.但最终却不得不引入了typename,究竟是什么原因呢?请看第二条,也就是typename的第二个用法。

2, 模板中标明“内嵌依赖类型名”

    这里有三个词,内嵌、依赖、类型名。那么什么是“内嵌依赖类型名(nested dependent type name)”?

    请看SGI STL里的一个例子,只是STL中count范型算法的实现:

template <class _InputIter, class _Tp>
typename iterator_traits<_InputIter>::difference_type
count(_InputIter __first, _InputIter __last, const _Tp& __value) {
  __STL_REQUIRES(_InputIter, _InputIterator);
  __STL_REQUIRES(typename iterator_traits<_InputIter>::value_type,
                 _EqualityComparable);
  __STL_REQUIRES(_Tp, _EqualityComparable);
  typename iterator_traits<_InputIter>::difference_type __n = 0;
  for ( ; __first != __last; ++__first)
    if (*__first == __value)
      ++__n;
  return __n;
}

    这里有三个地方用到了typename:返回值、参数、变量定义。分别是:

    typename iterator_traits<_InputIter>::difference_type

    typename iterator_traits<_InputIter>::value_type

    typename iterator_traits<_InputIter>::difference_type __n = 0;

    difference_type, value_type就是依赖于_InputIter(模板类型参数)的类型名。源码如下:

template <class _Iterator>
struct iterator_traits {
  typedef typename _Iterator::iterator_category iterator_category;
  typedef typename _Iterator::value_type        value_type;
  typedef typename _Iterator::difference_type   difference_type;
  typedef typename _Iterator::pointer           pointer;
  typedef typename _Iterator::reference         reference;
};

    内嵌是指定义在类名的定义中的。以上difference_type和value_type都是定义在iterator_traits中的。

    依赖是指依赖于一个模板参数。typename iterator_traits<_InputIter>::difference_type中difference_type依赖于模板参数_InputIter.

    类型名是指这里最终要指出的是个类型名,而不是变量。例如iterator_traits<_InputIter>::difference_type完全有可能是类iterator_traits<_InputIter>类里的一个static对象。而且当我们这样写的时候,C++默认就是解释为一个变量的。所以,为了和变量区分,必须使用typename告诉编译器。

    那么是不是所有的T::type_or_variable, 或者tmpl<T>:type_or_variable都需要使用typename呢?不是,有以下两个例外。

3 例外

(1)类模板定义中的基类列表。

    例如

 template<class T>
class Derived: public Base<T>::XXX
{
...
}

    (2)类模板定义中的初始化列表。

 Derived(int x) : Base<T>::xxx(x)
{
...
}

为什么这里不需要呢?因为编译器知道这里需要的是类型还是变量,

(1)基类列表里肯定是类型名,(2)初始化列表里肯定是成员变量名。

另一种解释:(这个还是比较好懂)

问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同?

template<class T> class Widget; // uses "class"
template<typename T> class Widget; // uses "typename"


  答案:没什么不同。在声明一个 template type parameter(模板类型参数)的时候,class 和 typename 意味着完全相同的东西。一些程序员更喜欢在所有的时间都用 class,因为它更容易输入。其他人(包括我本人)更喜欢 typename,因为它暗示着这个参数不必要是一个 class type(类类型)。少数开发者在任何类型都被允许的时候使用 typename,而把 class 保留给仅接受 user-defined types(用户定义类型)的场合。但是从 C++ 的观点看,class 和 typename 在声明一个 template parameter(模板参数)时意味着完全相同的东西。

  然而,C++ 并不总是把 class 和 typename 视为等同的东西。有时你必须使用 typename。为了理解这一点,我们不得不讨论你会在一个 template(模板)中涉及到的两种名字。

  假设我们有一个函数的模板,它能取得一个 STL-compatible container(STL 兼容容器)中持有的能赋值给 ints 的对象。进一步假设这个函数只是简单地打印它的第二个元素的值。它是一个用糊涂的方法实现的糊涂的函数,而且就像我下面写的,它甚至不能编译,但是请将这些事先放在一边——有一种方法能发现我的愚蠢:

template<typename C> // print 2nd element in
void print2nd(const C& container) // container;
{
 // this is not valid C++!
 if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // get iterator to 1st element
  ++iter; // move iter to 2nd element
  int value = *iter; // copy that element to an int
  std::cout << value; // print the int
 }
}


  我突出了这个函数中的两个 local variables(局部变量),iter 和 value。iter 的类型是 C::const_iterator,一个依赖于 template parameter(模板参数)C 的类型。一个 template(模板)中的依赖于一个 template parameter(模板参数)的名字被称为 dependent names(依赖名字)。当一个 dependent names(依赖名字)嵌套在一个 class(类)的内部时,我称它为 nested dependent name(嵌套依赖名字)。C::const_iterator 是一个 nested dependent name(嵌套依赖名字)。实际上,它是一个 nested dependent type name(嵌套依赖类型名),也就是说,一个涉及到一个 type(类型)的 nested dependent name(嵌套依赖名字)。

  print2nd 中的另一个 local variable(局部变量)value 具有 int 类型。int 是一个不依赖于任何 template parameter(模板参数)的名字。这样的名字以 non-dependent names(非依赖名字)闻名。(我想不通为什么他们不称它为 independent names(无依赖名字)。如果,像我一样,你发现术语 "non-dependent" 是一个令人厌恶的东西,你就和我产生了共鸣,但是 "non-dependent" 就是这类名字的术语,所以,像我一样,转转眼睛放弃你的自我主张。)

  nested dependent name(嵌套依赖名字)会导致解析困难。例如,假设我们更加愚蠢地以这种方法开始 print2nd:

template<typename C>
void print2nd(const C& container)
{
 C::const_iterator * x;
 ...
}


  这看上去好像是我们将 x 声明为一个指向 C::const_iterator 的 local variable(局部变量)。但是它看上去如此仅仅是因为我们知道 C::const_iterator 是一个 type(类型)。但是如果 C::const_iterator 不是一个 type(类型)呢?如果 C 有一个 static data member(静态数据成员)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是一个 global variable(全局变量)的名字呢?在这种情况下,上面的代码就不是声明一个 local variable(局部变量),而是成为 C::const_iterator 乘以 x!当然,这听起来有些愚蠢,但它是可能的,而编写 C++ 解析器的人必须考虑所有可能的输入,甚至是愚蠢的。

  直到 C 成为已知之前,没有任何办法知道 C::const_iterator 到底是不是一个 type(类型),而当 template(模板)print2nd 被解析的时候,C 还不是已知的。C++ 有一条规则解决这个歧义:如果解析器在一个 template(模板)中遇到一个 nested dependent name(嵌套依赖名字),它假定那个名字不是一个 type(类型),除非你用其它方式告诉它。缺省情况下,nested dependent name(嵌套依赖名字)不是 types(类型)。(对于这条规则有一个例外,我待会儿告诉你。)

  记住这个,再看看 print2nd 的开头:

template<typename C>
void print2nd(const C& container)
{
 if (container.size() >= 2) {
  C::const_iterator iter(container.begin()); // this name is assumed to
  ... // not be a type


  这为什么不是合法的 C++ 现在应该很清楚了。iter 的 declaration(声明)仅仅在 C::const_iterator 是一个 type(类型)时才有意义,但是我们没有告诉 C++ 它是,而 C++ 就假定它不是。要想转变这个形势,我们必须告诉 C++ C::const_iterator 是一个 type(类型)。我们将 typename 放在紧挨着它的前面来做到这一点:

template<typename C> // this is valid C++
void print2nd(const C& container)
{
if (container.size() >= 2) {
typename C::const_iterator iter(container.begin());
...
}
}


  通用的规则很简单:在你涉及到一个在 template(模板)中的 nested dependent type name(嵌套依赖类型名)的任何时候,你必须把单词 typename 放在紧挨着它的前面。(重申一下,我待会儿要描述一个例外。)

  typename 应该仅仅被用于标识 nested dependent type name(嵌套依赖类型名);其它名字不应该用它。例如,这是一个取得一个 container(容器)和这个 container(容器)中的一个 iterator(迭代器)的 function template(函数模板):

template<typename C> // typename allowed (as is "class")
void f(const C& container, // typename not allowed
typename C::iterator iter); // typename required


  C 不是一个 nested dependent type name(嵌套依赖类型名)(它不是嵌套在依赖于一个 template parameter(模板参数)的什么东西内部的),所以在声明 container 时它不必被 typename 前置,但是 C::iterator 是一个 nested dependent type name(嵌套依赖类型名),所以它必需被 typename 前置。

  "typename must precede nested dependent type names"(“typename 必须前置于嵌套依赖类型名”)规则的例外是 typename 不必前置于在一个 list of base classes(基类列表)中的或者在一个 member initialization list(成员初始化列表)中作为一个 base classes identifier(基类标识符)的 nested dependent type name(嵌套依赖类型名)。例如:

template<typename T>
class Derived: public Base<T>::Nested {
 // base class list: typename not
 public: // allowed
  explicit Derived(int x)
  : Base<T>::Nested(x) // base class identifier in mem
  {
   // init. list: typename not allowed
 
   typename Base<T>::Nested temp; // use of nested dependent type
   ... // name not in a base class list or
  } // as a base class identifier in a
  ... // mem. init. list: typename required
};


  这样的矛盾很令人讨厌,但是一旦你在经历中获得一点经验,你几乎不会在意它。

  让我们来看最后一个 typename 的例子,因为它在你看到的真实代码中具有代表性。假设我们在写一个取得一个 iterator(迭代器)的 function template(函数模板),而且我们要做一个 iterator(迭代器)指向的 object(对象)的局部拷贝 temp,我们可以这样做:

template<typename IterT>
void workWithIterator(IterT iter)
{
 typename std::iterator_traits<IterT>::value_type temp(*iter);
 ...
}


  不要让 std::iterator_traits<IterT>::value_type 吓倒你。那仅仅是一个 standard traits class(标准特性类)的使用,用 C++ 的说法就是 "the type of thing pointed to by objects of type IterT"(“被类型为 IterT 的对象所指向的东西的类型”)。这个语句声明了一个与 IterT objects 所指向的东西类型相同的 local variable(局部变量)(temp),而且用 iter 所指向的 object(对象)对 temp 进行了初始化。如果 IterT 是 vector<int>::iterator,temp 就是 int 类型。如果 IterT 是 list<string>::iterator,temp 就是 string 类型。因为 std::iterator_traits<IterT>::value_type 是一个 nested dependent type name(嵌套依赖类型名)(value_type 嵌套在 iterator_traits<IterT> 内部,而且 IterT 是一个 template parameter(模板参数)),我们必须让它被 typename 前置。

  如果你觉得读 std::iterator_traits<IterT>::value_type 令人讨厌,就想象那个与它相同的东西来代表它。如果你像大多数程序员,对多次输入它感到恐惧,那么你就需要创建一个 typedef。对于像 value_type 这样的 traits member names(特性成员名),一个通用的惯例是 typedef name 与 traits member name 相同,所以这样的一个 local typedef 通常定义成这样:

template<typename IterT>
void workWithIterator(IterT iter)
{
 typedef typename std::iterator_traits<IterT>::value_type value_type;

 value_type temp(*iter);
 ...
}


  很多程序员最初发现 "typedef typename" 并列不太和谐,但它是涉及 nested dependent type names(嵌套依赖类型名)规则的一个合理的附带结果。你会相当快地习惯它。你毕竟有着强大的动机。你输入 typename std::iterator_traits<IterT>::value_type 需要多少时间?

  作为结束语,我应该提及编译器与编译器之间对围绕 typename 的规则的执行情况的不同。一些编译器接受必需 typename 时它却缺失的代码;一些编译器接受不许 typename 时它却存在的代码;还有少数的(通常是老旧的)会拒绝 typename 出现在它必需出现的地方。这就意味着 typename 和 nested dependent type names(嵌套依赖类型名)的交互作用会导致一些轻微的可移植性问题。

  Things to Remember

  ·在声明 template parameters(模板参数)时,class 和 typename 是可互换的。

  ·用 typename 去标识 nested dependent type names(嵌套依赖类型名),在 base class lists(基类列表)中或在一个 member initialization list(成员初始化列表)中作为一个 base class identifier(基类标识符)时除外。

 

然后是老外的:

1. Specifying Type Parameters To Templates

  In template argument lists typename can be used interchangeably with class to indicate type parameters. Although there is no difference to the compiler, Alexandrescu recommends using class when the template argument is expected to be a class or struct, and typename for other classes of types. This is purely to encourage source readability.

2. Disambiguating Dependent Names

  The typename keyword is also used to indicate that a dependent name in a template definition refers to a type.

struct Foo {

  typedef int Type;

};

 

template<class T>

struct Bar {

  typedef typename T::Type BarType; // In a typedef

  void baz() {

     typename T::Type instance;     // In a declaration

  }

};

 

typedef Bar<Foo> FooBar;

 

C++模板编程:从泛型基础到元编程实战 泛型编程是现代C++的核心范式之一,它通过参数化类型实现代码复用,其原理是在编译期生成针对特定类型的特化代码,从而实现类型安全且高效的抽象。这种技术价值在于能够构建零开销的通用库组件,如标准模板库(STL)中的容器和算法,广泛应用于高性能计算、游戏引擎和基础架构开发。深入理解模板元编程机制,如SFINAE和编译期计算,是掌握现代C++高级特性的关键,能够帮助开发者设计出更灵活、更高效的泛型代码。 阅读详情

相关推荐

C++命名空间与函数模板实战:从using namespace std到现代代码组织

命名空间是C++中解决代码命名冲突的核心机制,通过为标识符提供逻辑分组,实现了大型项目的模块化组织。其原理在于创建独立的作用域隔离墙,避免全局命名污染,这一特性对于构建可维护的代码库至关重要。函数模板作为泛型编程的基础,通过参数化类型实现了代码复用,编译器在实例化时自动生成特定类型的函数版本,显著提升了开发效率与类型安全。在工程实践中,合理运用命名空间管理模板代码,结合ADL(参数依赖查找)规则,能够构建清晰、高效的现代C++库。本文深入探讨了命名空间与函数模板的协同工作机制,解析了using指令的风险与正

weixin_34318326的博客 479

template declarations(模板声明)中 class 和 typename 的异同

  template class Widget; // uses "class"template class Widget; // uses "typename"  在声明一个 template type parameter(模板类型参

博客搬往 http://begtostudy.cnblogs.com 1308

VM下安装linux虚拟机(ubuntu)和Intel parallel XE 2013(ifort2013)

VM下安装ubuntu和ifort2013跑自己的模式 由于新冠疫情,本人只能在家工作,很多重要的文件和程序都留在了办公室的linux机器上,工作无法正常开展。本来准备去办公室把机器搬回家不曾想学校所有门禁都关闭,不许进入,何时解禁也没有明确日期。科研不能等人,没条件科研只能想办法创造条件了。 以前在自己的笔记本(windows)上装过一次VM和ifort但无奈程序不能正常跑,所以之前就放弃了。本...

pangdahai3366的博客 1498

error: use 'template' keyword to treat 'xx' as a dependent template name

调用模板类限定的模板函数时,即形如:A&lt;typename_a&gt;::member_function&lt;typename_b&gt;()这样的调用时;必须使用关键字template进行说明,即改为:A&lt;typename_a&gt;:: template member_function&lt;typename_b&gt;();否则可能报错:error: use 'template'...

qq_41230365的博客 4784

centos7安装db2 version11.1

centos7安装db2 version11.1

AKA石头 1064

Arm Neoverse CMN-700 QoS与PrefetchTarget架构解析

在现代多核处理器系统中,内存访问性能优化是提升整体效能的关键。QoS(服务质量)技术通过优先级调控机制,确保关键任务获得更高的缓存带宽和内存访问权限。PrefetchTarget作为预取技术的一种实现,能够显著降低内存访问延迟,特别适用于AI训练和数据库系统等高性能计算场景。Arm Neoverse CMN-700通过RN SAM模块实现了硬件级的地址范围检测和优先级调控,支持最多8个独立内存区域的QoS配置。测试数据显示,合理配置QoS可使关键任务延迟降低40%,而PrefetchTarget技术则能减少

weixin_36197669的博客 315

111 C++ typename

3)基类列表中,比如class Derived :public Base<T>::Nested不能在public Base<T>::Nested前面加typename。2)如果IterT是vector<int>::iterator,那么value_type就代表int,temp的类型就是int。(1)如果iterator是嵌套类型将正确执行,这段代码的意思是定义一个 T::iterator类型的数据。可分别使用MyClass::A、MyClass::B和MyClass::C表示。//使用类型定义变量。

hunandede的博客 1062

CMake教程:C++ CMake自定义find_package并在其它项目使用

find_package 是 CMake 中一个非常重要的命令,用于在系统中找到外部库或包,并将其包含到项目中。: 要查找的包的名称。[version]: 可选的版本号。如果指定了版本号,CMake 会尝试找到该版本或更高版本的包。[REQUIRED]: 如果指定了这个关键字,找不到包时会产生一个错误并终止配置过程。: 指定要查找的包的组件。: 指定可选的组件,即使找不到这些组件,配置过程也会继续。: 指定查找包的模式,CONFIG表示查找配置文件,MODULE表示查找模块文件。

琅嬛福地 1563

C++语法|typename关键字

【代码】C++语法|typename关键字。

糖炒栗子 766

FPGA实现CAN接口(SJA1000)

学无止境,善于积累,每天积累一点点,成功就在眼前,加油! 1 CAN总线简介 CAN(Controller Area Network,控制器局域网 )总线是一个多主机异步串行总线,也是国际上应用最广泛的现场总线之一。在现场总线中,它是惟一被ISO国际标准化组织批准的现场总线。由于其成本低、容错能力强、支持分布式控制、通信速率高等优点在汽车、工业控制、航天等领域得到广泛应用。特别是由于CAN总线具有...

m0_46498597的博客 1万+

一文吃透 ABAP CDS SELECT:语法全景、关联与去重、可运行示例与实战心法

摘要: 本文深入解析ABAP中CDS视图的SELECT语法,重点介绍两种等价写法、关联与路径表达式优化、DISTINCT去重逻辑及WHERE/GROUP BY/HAVING/UNION等子句的应用。通过可运行的业务伙伴角色去重、关联路径查询及多角色筛选示例,演示如何将CDS特性转化为项目实践。强调关联复用性优于传统JOIN,并指出DISTINCT的权限边界与误用场景,帮助开发者从行式思维转向图式数据建模。(150字) 关键词: ABAP CDS、SELECT语法、路径表达式、DISTINCT去重、关联复用

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 392

Typedef与Typename的资料汇总

<br />定义易于记忆的类型名<br />  typedef 使用最多的地方是创建易于记忆的类型名,用它来归档程序员的意图。类型出现在所声明的变量名字中,位于 ''typedef'' 关键字右边。例如:typedef int size;<br />  此声明定义了一个 int 的同义字,名字为 size。注意 typedef 并不创建新的类型。它仅仅为现有类型添加一个同义字。你可以在任何需要 int 的上下文中使用 size:void measure(size * psz); size array[4

求知若饥,知行合一 1405

ardupilot 日志分析《xKF1信息》

ardupilot 日志分析系列将会把ardupilot所有的日志文档进行分析,为我们分析无人机的运行状态,炸鸡原因,传感器状态,电机状态,控制信息,滤波信息做准备。本节主要分析xKF1日志信息,欢迎批评指正。学习好ardupilot必须会分析飞行日志,从飞行日志中我们可以学到很多无人机的知识。无人机是综合知识的体现,涵盖:导航、控制、滤波、算法、协议等各种知识,只有更全面的学习,才能在无人机的道路上越走越远。

陌城烟雨 1226

c# getresponsestream返回byte[]_从 ReadInt32 开始的奇妙旅程(C#)

用 BinaryReader/BinaryWriter 时,由于它们不支持泛型参数,必须明确调用指定版本的方法才能工作(比如 ReadInt32),这用起来就很麻烦。如果可以支持泛型参数(比如 Read<int>),就可以自动量产代码了。所以,我们来为 BinaryReader/BinaryWriter 做个泛型扩展吧!if-else 版本从最简单的方法开始。早先 C# 的 switc...

weixin_39715290的博客 374

Nova — GPU/vGPU 虚拟机

目录 文章目录目录云主机使用显卡的实现方式虚拟显卡物理显卡直通物理显卡虚拟化 云主机使用显卡的实现方式 采用虚拟显卡 采用物理显卡直通 采用物理显卡虚拟化 虚拟显卡 虚拟显卡技术,主要用于虚拟机 Remote Console 领域,如:VNC(Virtual Network Computing,虚拟网络计算机),它能将完整的窗口界面通过网络,传输到另一台计算机的屏幕上。 VNC 主要由 VNC server 和 VNC viewer 两部分组成。用户需先将 VNC server 安装在被远程操控的计算

烟云的计算 2426

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

1.交换两个变量的数据(深入学习)

交换变量数据 本质是,第三个变量暂存其中一个数据。 使用第三个变量,法1 简单明了,不会产生歧义; 可以实现大类型(比如自定义的类或结构)的交换,可作为标准算法; 但是中间变量、拷贝数据开销不容小觑。 不使用第三个变量,法2.1,法2.2,法2.3(最推荐位运算) 本质是,a,b中的一个变量暂存a,b之间的某种关系,加减乘除皆可,最奇妙的最快速的是位运算 仅限于整数类型,位运算非常迅速,个人推荐。 交换变量的地址 本质,交换变量的地址 使用第三个变量,法3.1 在法1的基础上,指针作

稳健的我的博客 263

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++模板编程:从泛型基础到编译期计算的实战指南

泛型编程是现代编程语言中实现代码复用的核心技术,它通过参数化类型来创建独立于具体数据类型的算法和数据结构。其核心原理是在编译时进行类型替换和代码生成,从而实现静态多态,避免了运行时虚函数调用的开销。这种技术价值在于能够编写高度通用、类型安全且性能优异的代码,广泛应用于标准库容器、算法以及各种基础框架中。在C++中,模板是实现泛型编程的主要机制,通过模板特化、SFINAE等高级技巧,开发者可以在编译期进行复杂的类型计算和条件判断。本文以C++模板为例,深入解析了模板实例化、类型推导等关键机制,并探讨了如何利用

weixin_34221654的博客 237

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

关于C++从属名称

<br />在《EFFECTIVE C++ 3.0》的第41条款提到:<br />在使用从属嵌套类型名称是需要使用typename来修饰,因为类属模板的实现是“编译时”的,若下状况<br /> void print(const T& con)<br /> {<br />  if(con.size() >= 2)<br />  {<br />   T::const_iterator iter(con.begin());<br />   ++iter;<br />   int value = *iter;<br

hillbird的专栏 1097

java函数式编程基础(二)

3、lambda表达式 lambda表达式可以说是函数式编程的核心。lambda表达式即匿名函数,它是一段没有函数名的函数体,可以作为参数直接传递给相关的调用者。lambda表达式极大地增强了Java语言的表达能力。 下例展示了lambda表达式的使用,在forEach()函数中,传入的就是一个lambda表达式,它完成了对元素的标准输出操作。可以看到这段表达式并不像函数一样有名字,非常类似匿名内部类,它只是简单地描述了应该执行的代码段。 List<Integer> list = Array

m0_38060516的博客 314

Essential C++学习记录&笔记整理13(提供重载函数,定义并使用模板(template)函数)

为什么俩搁一块呢,就是方便叙述,一层扣一层的知识。 提供重载函数 为什么要用重载函数? ①将一组实现代码不同但工作内容相似的函数加以重载,可以让函数的用户更容易更灵活使用这些函数,如果没有重载机制,我们就得为每个函数提供不同的名称。 解释一下,就是我想写一个函数,我想让这个函数以不同的参数表(或者说我想提供不同的实参表来调用一个函数),我有这个需求,所以我要用重载函数,来减轻我的工作量,让我不再...

Bqv它不想做功的博客 245

Effective C++笔记 (7.模板与泛型编程)

条款41:了解隐式接口和编译器多态Templates及泛型编程的世界,与面向对象有根本上的不同。在此世界中显示接口和运行期多态仍然存在,但重要性降低。反倒是隐式接口和编译期多态移到前面了。加诸于template参数身上的隐式接口,就像加诸于class对象身上的显示接口一样真实,而且两者都在编译期完成检查。就像你无法以一种“与class提供之显示接口矛盾”的方式来使用对象(代码将通不过编译),你也无...

HHXUN的博客 418

C++模板编程:从基础语法到实战应用,掌握泛型编程核心技能

泛型编程是现代编程语言中实现代码复用的核心技术,它允许开发者编写与具体数据类型无关的通用算法和数据结构。其核心原理是通过参数化类型,在编译期生成针对特定类型的特化代码,从而实现类型安全与高性能的统一。这一技术价值在于显著提升了代码的抽象能力和复用性,避免了为不同数据类型重复编写相似逻辑的冗余工作。在C++中,模板是实现泛型编程的主要机制,广泛应用于标准模板库(STL)的容器(如vector、map)和算法中。通过函数模板和类模板,开发者可以构建灵活高效的通用组件,例如实现类型安全的通用算法或自定义智能指针。

Hi, Sun 610

C++模板编程:从泛型基础到STL核心机制解析

泛型编程是现代编程语言中实现代码复用的核心技术,它通过参数化类型让算法和数据结构与具体类型解耦。其核心原理是在编译时根据实际使用的类型生成特化代码,从而实现类型安全的高效复用。这一技术价值在于显著减少代码重复、提升开发效率,并为构建可扩展的软件库奠定基础。在C++中,模板是实现泛型编程的主要工具,广泛应用于标准模板库(STL)的容器、算法和迭代器组件。通过函数模板和类模板,开发者可以创建通用的数据结构和算法,例如实现类型无关的排序函数或自定义容器。本文以C++模板为切入点,深入解析其编译机制、特化技术以及与

weixin_34242819的博客 303

C++模板进阶实战:从非类型参数到编译期多态的设计模式

C++模板作为泛型编程的核心机制,通过类型参数化实现了代码复用和类型安全。其原理在于编译期生成特化代码,为不同类型提供相同逻辑的实例化。这一技术价值在于实现零成本抽象,将运行时开销转移到编译期,同时增强类型安全性。在实际应用场景中,模板不仅用于容器和算法,更是构建高效、可扩展系统的基础设施。通过非类型模板参数,可以将常量值“烙”进类型,实现编译期确定大小的数据结构,如环形缓冲区,从而提升性能。模板特化(包括全特化和偏特化)允许为特定类型提供定制实现,这是实现编译期多态和类型分发的基础。结合这些特性,可以构建

weixin_30621959的博客 316

c++——typename关键字

介绍typename之前,应先了解几个概念: 1. 限定名与非限定名 限定名,顾名思义,是限定了命名空间的名称。 #include <iostream> int main() { std::cout << "Hello world!" << std::endl; } std::限定了std这个命名空间,故称为限定名。 #include <iostream> using namespace std; int main() {

www_dong的博客 1258

了解C++中typename的双重意义

typename的最多用法就是模板声明中,以下两种声明没有任何区别。 template &amp;lt;class T&amp;gt; class Test; template &amp;lt;typename T&amp;gt; class Test; typename的另一个作用就是使用嵌套依赖类型(nested depended name)。 #include &amp;lt;iostream&amp;gt; #incl...

孙堂吉de博客 690
上一篇: 今日e语-6月30日
下一篇: C++操作符重载,有点晕。。。
骑行的蜗牛
博客等级 码龄21年 107粉丝 86原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值