- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
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 usageThe 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
::type
We’d prefer something like the following:template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usageNote 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 nameVec
is aname for the familystd::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 sentencetemplate<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 forstd::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_options
和 using 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/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!