N4567的标准草案表明,如果根据12.1第4段,默认的默认构造函数被定义为已删除:
X是一个联合,它的所有变体成员都是const限定类型(或其数组),
换句话说,它等同于说,如果其变体成员之一不是const限定的,则上述规则不适用.我的问题是:
考虑以下代码:
int **p = 0;
class S {
public:
explicit operator int**&() {
return p;
}
};
int main() {
S a;
int *const*&b (a); // error in both g++-7 and clang-5.0 with "-std=c++17"
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你会同意的
int**到int*const*是可能的,并int *const*&b (a)是直接初始化.首先,我们指的是11.6.3条第5款[dcl.init.ref]从N4700.
参考输入" CV1
T1 (= int*const*)"是通过类型"的表达初始化CV2T2 (= S)"如下:
- 如果引用是左值引用和初始化表达式
- ...
- 有一个类类型(即,
T2是类类型),其中T1与引用无关T2,并且可以转换为类型为" cv3T3" 的左值,其中" cv1 …
根据17.7.3 [temp.expl.spec]第5段(N4659),
...显式专用类模板的成员以与普通类成员相同的方式定义,而不是使用
template<>语法.定义显式专用成员类的成员时也是如此.但是,template<>用于定义专门用作类模板的显式专用成员类模板的成员.
明确的专业化E肯定不属于大胆的情况,它仍然需要template<>.这是为什么?
template<class T> struct A {
enum E : T;
};
template<> enum A<int>::E : int { eint };
Run Code Online (Sandbox Code Playgroud) 省略模板参数是可能的,因为标准在17.9.1第3段[temp.arg.explicit](N4700)中说:
可以从显式模板参数列表中省略可以从默认模板参数 s 推导或获得的尾随模板参数...
另一方面,标准有一个相互冲突的规则,如17.9.2,第2段[temp.deduct]显示(强调我的):
...具体而言,在针对给定函数模板评估显式指定的模板参数列表时,将执行以下步骤:
- 如果指定的模板参数与实际的模板参数(即类型,非类型,模板)不匹配,或者参数多于参数且没有参数是模板参数包,或者没有参数每个非pack参数的参数,类型推导失败.
- ...
本段建议如果我们使用显式模板参数列表,则应指定所有模板参数,这与上一段明显矛盾.那么,意图是什么?
14.1 [temp.param],第2段
...
typename后跟一个unqualified-id命名一个模板类型参数.typename后跟一个qualified-id表示非类型参数声明中的类型 ...
我对粗体文本的含义有点困惑.具体来说,typename可以出现在两个不同的上下文(类型说明符或模板参数)中,但这是指哪一个?
对于前一种情况,我考虑过:
struct A {
struct X { };
int X;
};
struct B {
struct X { };
};
template<class T> void f(T t) {
typename T::X x; // T can be A or B
}
Run Code Online (Sandbox Code Playgroud)
但是,既不是A::X也不B::X是非类型参数声明(它们是成员声明).
对于后一种情况,我不确定为什么这是必要的.为什么不用qualified-id直接写下它的类型呢?参数化是必要的吗?
正如C11草案所述,我可以向这两个人保证:
...结构对象中可能有未命名的填充,但不是在它的开头.
结构或联合的末尾可能有未命名的填充.
但是,如果任何两个成员之间的填充是可以接受的,那对我来说是不明确的.这是因为,通过说第二段,标准似乎暗示填充只能在结构或联合的末尾.例如,假设int占用4个字节,
#include <stdio.h>
struct s {
char c;
int a;
};
int main(void) {
printf("%d\n", sizeof(struct s));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我可以得出结论,在c和之间没有填充a吗?
考虑以下代码片段:
#include <iostream>
int a;
void address_of_a(void) {
std::cout << &a << std::endl;
}
namespace N {
int a;
void address_of_a(void) {
std::cout << &a << std::endl;
}
};
int main(void) {
address_of_a();
N::address_of_a();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
全局命名空间和命名命名空间N被赋予外部链接,因为N4567的 3.5 [basic.link] 第 4 段说
未命名的命名空间或在未命名的命名空间内直接或间接声明的命名空间具有内部链接。所有其他命名空间都有外部链接...
此外,::a和N::a也被给予外部链接,因为它们不适用于 3.5 [basic.link] 第 3 段,
具有命名空间范围 (3.3.6) 的名称具有内部链接,如果它是
- 显式声明为静态的变量、函数或函数模板;或者,
- 非易失性 const 限定类型的变量,既没有显式声明为 extern,也没有事先声明为具有外部链接;或者
- 匿名联合体的数据成员。
但对于 3.5 [basic.link] 第 4 段,
...具有命名空间范围且未在上面给出内部链接的名称,如果它是以下名称,则与封闭命名空间具有相同的链接
- 一个变量; 或者 …
网络上的一些程序似乎在不使用int指令的情况下也能完成相同的工作,例如直接写入bx800. 在这种情况下,BIOS 究竟如何知道是否应该将某些文本写入控制台?是否保证初始中断发生?如果是这样,ah那么完成相同工作的等效装配线(或中断向量 和 的组合)是什么时候?