- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
假设我们有两种类型(完整和不完整):
struct CompleteType{};
struct IncompleteType;
#include <type_traits>
template <typename = X(T)>
struct Test : std::false_type {};
template <>
struct Test<T> : std::true_type {};
T
可以
CompleteType
或
IncompleteType
这里和
X(T)
可以
T
,
decltype(T())
或
decltype(T{})
(假设
X(T)
是一个宏)。
std::cout << std::boolalpha << Test<>::value << std::endl;
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true --- (1, 2)
decltype(T{}) true --- (1, 2)
error: invalid use of incomplete type 'IncompleteType'
即使在不使用 decltype(T())
的情况下,即使在具有不完整类型的模板类声明上(对于 decltype(T{})
和 T
,但不是简单的 Test<>::value
)也给出在代码中。 error: too few template arguments for class template 'Test'
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true true
decltype(T{}) true true
X(T) \ T CompleteType IncompleteType
T true true
decltype(T()) true --- (1)
decltype(T{}) true --- (2)
error C2514: 'IncompleteType' : class has no constructors
error C2440: '<function-style-cast>' : cannot convert from 'initializer-list' to 'IncompleteType' Source or target has incomplete type
std::cout << typeid(X(IncompleteType)).name() << std::endl;
这样的简单字符串不会在所有编译器上编译
X
的所有变体(除了 vc++
和
X(T) == T
)。
最佳答案
我相信在这种情况下,Clang 和 MSVC 的行为是符合标准的。我认为 GCC 在这里采取了一些捷径。
让我们先把一些事实摆在桌面上。 decltype
的操作数表达式是所谓的未计算操作数,由于它们最终从未计算过,因此处理方式略有不同。
特别是对类型完整的要求较少。基本上,如果您有任何临时对象(作为表达式中涉及的函数或运算符中的参数或返回值),它们不需要是完整的(参见第 5.2.2/11 和 7.1.6.2/5 节)。但这只是解除了通常的“不能声明不完整类型的对象”的限制,并没有解除对不完整类型的另一个限制,即“不能调用不完整类型的成员函数”。这就是踢球者。
表达式 decltype(T())
或 decltype(T{})
,其中 T
不完整,必须查找 T
类型的构造函数,因为它是该类的(特殊)成员函数。只是因为它是一个构造函数调用,这会造成一些歧义(即,它只是创建了一个临时对象?还是调用了一个构造函数?)。如果是任何其他成员功能,则不会有任何争论。幸运的是,该标准确实解决了这场争论:
12.2/1
Even when the creation of the temporary object is unevaluated (Clause 5) or otherwise avoided (12.8), all the semantic restrictions shall be respected as if the temporary object had been created and later destroyed. [ Note: even if there is no call to the destructor or copy/move constructor, all the semantic restrictions, such as accessibility (Clause 11) and whether the function is deleted (8.4.3), shall be satisfied. However, in the special case of a function call used as the operand of a decltype-specifier (5.2.2), no temporary is introduced, so the foregoing does not apply to the prvalue of any such function call. - end note ]
T f();
函数,然后您声明
decltype(f())
,然后
T
不需要完整或对是否有可用和可访问的构造函数/析构函数进行任何语义检查。
std::declval
的原因。实用程序,因为当您无法使用时
decltype(T())
,您可以使用
decltype(std::declval<T>())
, 和
declval
只不过是一个返回类型为
T
的纯右值的(假)函数.但当然,
declval
旨在用于不太重要的情况,例如
decltype( f( std::declval<T>() ) )
哪里
f
将是一个采用
T
类型对象的函数.和
declval
不要求类型是完整的(见第 20.2.4 节)。这基本上是您解决整个问题的方法。
T()
的类型。或
T{}
是。我认为一旦 GCC 发现
T
引用一个类型名(不是函数名),它推断这是一个构造函数调用,因此,无论查找发现什么作为实际被调用的构造函数,返回类型都是
T
(好吧,严格来说构造函数没有返回类型,但你明白我的意思)。这里的要点是,在未计算的表达式中,这可能是一个有用(更快)的捷径。但据我所知,这不是符合标准的行为。
CompleteType
如果构造函数被删除或私有(private),那么这也与标准的上述引用段落直接矛盾。在这种情况下,编译器需要强制执行所有语义限制,即使不计算表达式也是如此。
Note that simple string like
std::cout << typeid(X(IncompleteType)).name() << std::endl;
does not compile on all compilers for all variants of X (except for vc++ and X(T) == T).
typeid
和
sizeof
运算符类似于
decltype
然而,从它们的操作数未计算的意义上讲,它们都有一个额外的要求,即结果表达式的类型必须是完整类型。可以想象,编译器可以解析
typeid
对于不完整的类型(或至少,具有部分类型信息),但标准需要一个完整的类型,这样编译器就不必这样做了。我想这就是 MSVC 正在做的事情。
T()
和
T{}
案例失败的原因与
decltype
相同(正如我刚刚解释的),以及
X(T) == T
案例失败,因为
typeid
需要一个完整的类型(但 MSVC 设法解除了该要求)。在 GCC 上,它由于
typeid
而失败需要所有
X(T)
的完整类型情况(即 GCC 采取的捷径不会影响
sizeof
或
typeid
的结果)。
关于c++ - 模板代码中的类型不完整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22770318/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!