gpt4 book ai didi

c++ - C++中 "using"关键字背后的逻辑是什么?

转载 作者:IT老高 更新时间:2023-10-28 11:55:47 27 4
gpt4 key购买 nike

C++中“using”关键字背后的逻辑是什么?

它用于不同的情况,我正在努力寻找如果所有这些有共同点并且有原因为什么使用“using”关键字。

using namespace std; // to import namespace in the current namespace
using T = int; // type alias
using SuperClass::X; // using super class methods in derived class

最佳答案

在 C++11 中,using用于 type alias 时的关键字等同于 typedef .

7.1.3.2

A typedef-name can also be introduced by an alias-declaration. Theidentifier following the using keyword becomes a typedef-name and theoptional attribute-specifier-seq following the identifier appertainsto that typedef-name. It has the same semantics as if it wereintroduced by the typedef specifier. In particular, it does not definea new type and it shall not appear in the type-id.

Bjarne Stroustrup 提供了一个实际示例:

typedef void (*PFD)(double);    // C style typedef to make `PFD` a pointer to a function returning void and accepting double
using PF = void (*)(double); // `using`-based equivalent of the typedef above
using P = [](double)->void; // not valid in C++11
using P = auto(double)->void // Fixed thanks to DyP

C++11 之前的 using关键字可以将成员函数带入作用域。在 C++11 中,您现在可以对构造函数执行此操作(另一个 Bjarne Stroustrup 示例):

class Derived : public Base { 
public:
using Base::f; // lift Base's f into Derived's scope -- works in C++98
void f(char); // provide a new f
void f(int); // prefer this f to Base::f(int)

using Base::Base; // lift Base constructors Derived's scope -- C++11 only
Derived(char); // provide a new constructor
Derived(int); // prefer this constructor to Base::Base(int)
// ...
};

Ben Voight 为不引入新关键字或新语法的基本原理提供了一个很好的理由。该标准希望尽可能避免破坏旧代码。这就是为什么在提案文件中您会看到像 Impact on the Standard 这样的部分。 , Design decisions ,以及它们如何影响旧代码。在某些情况下,提案看起来确实是一个好主意,但可能没有吸引力,因为它太难实现、太困惑或与旧代码相矛盾。


这是 2003 年的旧论文 n1449 .理由似乎与模板有关。警告:由于从 PDF 复制过来,可能会出现拼写错误。

First let’s consider a toy example:

template <typename T>
class MyAlloc {/*...*/};

template <typename T, class A>
class MyVector {/*...*/};

template <typename T>

struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p; // sample usage

The fundamental problem with this idiom, and the main motivating factfor this proposal, is that the idiom causes the template parameters toappear in non-deducible context. That is, it will not be possible tocall the function foo below without explicitly specifying templatearguments.

template <typename T> void foo (Vec<T>::type&);

So, the syntax is somewhat ugly. We would rather avoid the nested ::typeWe’d prefer something like the following:

template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage

Note that we specifically avoid the term “typedef template” andintroduce the new syntax involving the pair “using” and “=” to help avoidconfusion: we are not defining any types here, we are introducing asynonym (i.e. alias) for an abstraction of a type-id (i.e. typeexpression) involving template parameters. If the template parametersare used in deducible contexts in the type expression then wheneverthe template alias is used to form a template-id, the values of thecorresponding template parameters can be deduced – more on this willfollow. In any case, it is now possible to write generic functionswhich operate on Vec<T> in deducible context, and the syntax isimproved as well. For example we could rewrite foo as:

template <typename T> void foo (Vec<T>&);

We underscore here that one of the primary reasons for proposingtemplate aliases was so that argument deduction and the call to foo(p)will succeed.


后续论文n1489解释为什么 using而不是使用typedef :

It has been suggested to (re)use the keyword typedef — as done in thepaper [4] — 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 tointroduce a type alias. However, it also displays severaldisavantages among which the confusion of using a keyword known tointroduce an alias for a type-name in a context where the alias doesnot designate a type, but a template; Vec is not an alias for atype, and should not be taken for a typedef-name. The name Vec is aname for the family std::vector< [bullet] , MyAllocator< [bullet] > >– where the bullet is a placeholder for a type-name. Consequently wedo 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 asynonym for std::vector<T, MyAllocator<T> >. With that reading, thenew syntax for aliasing seems reasonably logical.

我认为重要的区别在于这里,aliases 而不是 types。同一文档中的另一个引述:

An alias-declaration is a declaration, and not a definition. An alias-declaration introduces a name into a declarative region as an aliasfor the type designated by the right-hand-side of the declaration. Thecore of this proposal concerns itself with type name aliases, but thenotation can obviously be generalized to provide alternate spellingsof namespace-aliasing or naming set of overloaded functions (see ✁2.3 for further discussion). [My note: That section discusses what that syntax can look like and reasons why it isn't part of the proposal.] It may be noted that the grammar production alias-declaration is acceptable anywhere a typedefdeclaration or a namespace-alias-definition is acceptable.

总结,using 的角色:

  • 模板别名(或模板类型定义,前者是首选名称)
  • 命名空间别名(即 namespace PO = boost::program_optionsusing PO = ... 等效)
  • 文件说A typedef declaration can be viewed as a special case of non-template alias-declaration .这是一种美学变化,在这种情况下被认为是相同的。
  • 将某些东西带入作用域(例如,namespace std 进入全局作用域)、成员函数、继承构造函数

不能用于:

int i;
using r = i; // compile-error

改为:

using r = decltype(i);

命名一组重载。

// bring cos into scope
using std::cos;

// invalid syntax
using std::cos(double);

// not allowed, instead use Bjarne Stroustrup function pointer alias example
using test = std::cos(double);

关于c++ - C++中 "using"关键字背后的逻辑是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20790932/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com