C++11 中的“typedef”和“using”有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10747810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:24:37  来源:igfitidea点击:

What is the difference between 'typedef' and 'using' in C++11?

c++c++11typedefusing-declaration

提问by Klaim

I know that in C++11 we can now use usingto write type alias, like typedefs:

我知道在 C++11 中我们现在可以using用来写类型别名,比如typedefs:

typedef int MyInt;

Is, from what I understand, equivalent to:

是,据我所知,相当于:

using MyInt = int;

And that new syntax emerged from the effort to have a way to express "template typedef":

而这种新的语法是为了有一种表达“ template typedef”的方式而出现的:

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

But, with the first two non-template examples, are there any other subtle differences in the standard? For example, typedefs do aliasing in a "weak" way. That is it does not create a new type but only a new name (conversions are implicit between those names).

但是,对于前两个非模板示例,标准中是否还有其他细微的差异?例如,typedefs 以“弱”的方式进行混叠。也就是说,它不会创建新类型,而只会创建新名称(这些名称之间的转换是隐式的)。

Is it the same with usingor does it generate a new type? Are there any differences?

它与相同using还是生成新类型?有什么区别吗?

采纳答案by Jesse Good

They are equivalent, from the standard (emphasis mine) (7.1.3.2):

它们是等效的,来自标准(强调我的)(7.1.3.2):

A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by the typedef specifier.In particular, it does not define a new type and it shall not appear in the type-id.

typedef-name 也可以通过别名声明引入。using 关键字后面的标识符成为 typedef-name,标识符后面的可选属性说明符序列属于该 typedef-name。它与由 typedef 说明符引入的语义相同。特别是,它没有定义新的类型,也不会出现在 type-id 中。

回答by Zhongming Qu

They are largely the same, except that:

它们大致相同,除了:

The alias declaration is compatible with templates, whereas the C style typedef is not.

别名声明与模板兼容,而 C 风格的 typedef 则不兼容。

回答by 4xy

The usingsyntax has an advantage when used within templates. If you need the type abstraction, but also need to keep template parameter to be possible to be specified in future. You should write something like this.

使用中的模板中使用时的语法有优势。如果需要类型抽象,还需要保留模板参数以便将来可以指定。你应该写这样的东西。

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

But usingsyntax simplifies this use case.

但是使用语法简化了这个用例。

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }

回答by Validus Oculus

They are essentially the same but usingprovides alias templateswhich is quite useful. One good example I could find is as follows:

它们本质上是相同的,但using提供了alias templates非常有用的功能。我能找到的一个很好的例子如下:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

So, we can use std::add_const_t<T>instead of typename std::add_const<T>::type

所以,我们可以使用std::add_const_t<T>代替typename std::add_const<T>::type

回答by RoboticForest

I know the original poster has a great answer, but for anyone stumbling on this thread like I have there's an important note from the proposalthat I think adds something of value to the discussion here, particularly to concerns in the comments about if the typedefkeyword is going to be marked as deprecated in the future, or removed for being redundant/old:

我知道原始海报有一个很好的答案,但是对于像我这样在这个线程上磕磕绊绊的人来说,提案中有一个重要的说明,我认为它为这里的讨论增加了一些价值,尤其是评论中关于typedef关键字是否为将来会被标记为已弃用,或因冗余/旧而被删除:

It has been suggested to (re)use the keyword typedef ... to introduce template aliases:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

That notation has the advantage of using a keyword already known to introduce a type alias. However, it also displays several disavantages [sic] among which the confusion of using a keyword known to introduce an alias for a type-name in a context where the alias does not designate a type, but a template; Vecis notan alias for a type, and should not be taken for a typedef-name. The name Vecis a name for the family std::vector<?, MyAllocator<?> >– where the bullet is a placeholder for a type-name.Consequently we do not propose the “typedef” syntax.On the other hand the sentence

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

can be read/interpreted as: from now on, I'll be using Vec<T>as a synonym for std::vector<T, MyAllocator<T> >. With that reading, the new syntax for aliasing seems reasonably logical.

有人建议(重新)使用关键字 typedef ... 来引入模板别名:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

这种表示法的优点是使用已知的关键字来引入类型别名。然而,它也显示了几个缺点 [原文如此],其中在别名不是指定类型而是模板的上下文中使用已知的关键字为类型名称引入别名的混淆;Vec不是一个类型的别名,不应该采取一个typedef名。名称Vec是家族的名称std::vector<?, MyAllocator<?> >——其中项目符号是类型名称的占位符。因此,我们不建议使用“typedef”语法。另一方面,句子

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

可以阅读/解释为:从现在开始,我将Vec<T>用作std::vector<T, MyAllocator<T> >. 通过这种阅读,别名的新语法似乎合乎逻辑。

To me, this implies continued support for the typedefkeyword in C++ because it can still make code more readable and understandable.

对我来说,这意味着继续支持typedefC++ 中的关键字,因为它仍然可以使代码更具可读性和可理解性

Updating the usingkeyword was specifically for templates, and (as was pointed out in the accepted answer) when you are working with non-templates usingand typedefare mechanically identical, so the choice is totally up to the programmer on the grounds of readability and communication of intent.

更新using关键字专门针对模板,并且(如已接受的答案中指出的那样)当您使用非模板using并且typedef在机械上相同时,因此基于可读性和意图交流的选择完全取决于程序员.

回答by marski

Both keywords are equivalent, but there are a few caveats. One is that declaring a function pointer with using T = int (*)(int, int);is clearer than with typedef int (*T)(int, int);. Second is that template alias form is not possible with typedef. Third is that exposing C API would require typedefin public headers.

这两个关键字是等效的,但有一些注意事项。一是声明函数指针 withusing T = int (*)(int, int);比 with 更清晰typedef int (*T)(int, int);。其次是模板别名形式不能与typedef. 第三是公开 C API 需要typedef在公共头文件中。