看看这个片段:
namespace A {
int fn();
}
namespace B {
int fn();
}
// namespace Ns {
using namespace A;
using namespace B;
using A::fn;
int z = fn();
// }
Run Code Online (Sandbox Code Playgroud)
这段代码不能编译,因为fn()它不明确int z = fn();
如果我将using's并z放入命名空间(删除两个//),代码将编译.这是为什么?全局命名空间有什么特别之处?
我一直想知道决定,为什么override和final必须在成员函数声明符之后:
struct Base {
virtual void virtFun();
};
struct Foo: Base {
virtual void virtFun() override;
};
Run Code Online (Sandbox Code Playgroud)
对我来说,放置override/ final代替以下内容更合乎逻辑virtual:
struct Base {
virtual void virtFun();
};
struct Foo: Base {
override void virtFun();
};
Run Code Online (Sandbox Code Playgroud)
这背后有原因吗?也许与C++ 11之前有一些兼容性问题?
C++ 11引入了新的值类别,其中之一就是xvalue.
它被Stroustrup 解释为(im类别):"它是一个值,它具有身份,但可以从"移动".
另一个来源, cppreference解释说:
glvalue是一个表达式,其评估决定了对象,位域或函数的身份;
并且xvalue是一个glvalue,所以这个陈述也是如此xvalue.
现在,我认为如果有一个xvalue身份,那么我可以检查两个xvalues是否引用同一个对象,所以我取一个地址xvalue.事实证明,不允许:
int main() {
int a;
int *b = &std::move(a); // NOT ALLOWED
}
Run Code Online (Sandbox Code Playgroud)
xvalue具有身份意味着什么?
我想if constexpr完全理解.
我理解,如果if constexpr(expr)在模板中使用,并且expr依赖于模板参数,那么在实例化期间,只有一个then/ else分支将被实例化,另一个将被丢弃.
我有两个问题:
expr不依赖于模板参数,那么if constexpr(expr)将不会丢弃任何分支?如果是,标准在哪里这样说?我没有看到标准有什么例外,丢弃只在expr依赖时发生.if constexpr模板以外有用吗?如果是,这有什么用例?你能举出一些例子来了解它的用处吗?该标准说明了dcl.constexpr/6中的模板constexpr函数/构造函数:
如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,那么该特化仍然是constexpr函数或constexpr构造函数,即使调用这样的函数不能出现在常量表达式中.如果模板的特化不满足constexpr函数或constexpr构造函数在被视为非模板函数或构造函数时的要求,则模板格式错误,无需诊断.
有趣的是:
无法满足... constexpr构造函数的要求,该特化仍然是... constexpr构造函数
因此,即使构造函数被标记constexpr,也不能在常量表达式中使用它.
为什么存在这个规则?constexpr当功能不满足要求时,为什么不删除?
目前的行为在两个方面很糟糕:
constexpr默默地删除.constexpr构造函数),将动态初始化,没有任何错误/警告(因为构造函数不是"真正"constexpr).这条规则是否有一些优点,这可以平衡它的缺点?
什么时候可以sizeof(size_t)和sizeof(ptrdiff_t)不同?
这有什么现实世界的例子吗?
注意,我知道所有标准都说这些类型是实现定义的.但是,所有的实现,我知道,sizeof(size_t)和sizeof(ptrdiff_t)平等.也许是因为一些奇怪(或不那么奇怪)的原因,它们可能会有所不同.
看起来,这sizeof(ptrdiff_t)<sizeof(size_t)不是一个非常有用的情况,因为对于大型数组,指针算法将非常有限.
另一种情况sizeof(ptrdiff_t)>sizeof(size_t)可能稍微有用,因为所有指针减法都将在数组上定义(如果有一个更大的数组PTRDIFF_MAX,则将为所有远程元素定义指针减法,与通常的情况相反sizeof(ptrdiff_t)==sizeof(size_t)).有没有真正的实现呢?这种方法是否还有其他有用的属性?
该标准定义了两种类型的布局兼容性.但是,我没有看到标准中的任何地方,当两种类型的布局兼容时后果是什么.似乎布局兼容是一种在任何地方都不使用的定义.
布局兼容的目的是什么?
注意:据说,它可能意味着类型具有相同的布局(offsetof对于每个相应的成员是相同的),因此,例如,对于简单的可复制类型,可以在它们之间复制基础字节.但是我没有在标准中看到这样的东西.
在数值计算中,通常需要将数字缩放到安全范围内.
例如,计算欧几里德距离:sqrt(a^2+b^2).在这里,如果幅度a还是b过小/大,则溢/上溢可能发生.
解决此问题的常用方法是将数字除以最大幅度数.但是,这个解决方案是:
所以我认为不是除以最大幅度数,而是将它乘以一个接近2次幂的倒数.这似乎是一个更好的解决方案,如:
所以,我想创建一个小实用程序函数,它有一个像这样的逻辑(通过^,我的意思是取幂):
void getScaler(double value, double &scaler, double &scalerReciprocal) {
int e = <exponent of value>;
if (e<-1022) { scaler=2^-1022; scalerReciprocal = 2^1022; }
} else if (e>1022) { scaler=2^1022; scalerReciprocal = 2^-1022; }
} else { scaler=2^e; scalerReciprocal = 2^(2046-e); }
}
Run Code Online (Sandbox Code Playgroud)
这个函数应该返回一个标准化的scaler&scalerReciprocal,两个都是2的幂数,scaler它接近于value,并且scalerReciprocal是它的倒数scaler.
为最大允许指数scaler/ scaleReciprocal是-1022..1022(我不想用低于正常工作scaler,为次正规数可能会很慢). …
在某些情况下,我们使用标签来区分函数。标签通常是一个空结构:
struct Tag { };
Run Code Online (Sandbox Code Playgroud)
假设我有一个使用此标签的函数:
void func(Tag, int a);
Run Code Online (Sandbox Code Playgroud)
现在,我们调用这个函数:
func(Tag(), 42);
Run Code Online (Sandbox Code Playgroud)
并检查生成的 x86-64 反汇编,godbolt:
mov edi, 42
jmp func(Tag, int) # TAILCALL
Run Code Online (Sandbox Code Playgroud)
没关系,标签得到了完全优化:没有为其分配寄存器/堆栈空间。
但是,如果我查看其他平台,就会发现该标签存在一些。
在 ARM 上,r0用作标签,并且它被归零(似乎没有必要):
mov r1, #42
mov r0, #0
b func(Tag, int)
Run Code Online (Sandbox Code Playgroud)
对于 MSVC,ecx被用作标记,并且它是从堆栈中“初始化”的(同样,似乎没有必要):
movzx ecx, BYTE PTR $T1[rsp]
mov edx, 42 ; 0000002aH
jmp void func(Tag,int) ; func
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否有一种标签技术在所有这些平台上都得到了同样的优化?
注意:我没有找到 SysV ABI 指定可以在参数传递时优化空类的地方...(甚至,Itanium C++ ABI说:“空类的传递与普通类没有什么不同”。)
看这个简单的例子:
template <typename T>
const T const_create() {
return T();
}
struct Foo { };
int main() {
auto &x = const_create<Foo>(); // compiles
// auto &x = const_create<int>(); // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)
为什么版本可以Foo编译,而int不能编译?换句话说,为什么const要从返回类型中删除const_create<int>?它的工作方式就像它返回一样int,不是const int。这不是语言上的矛盾吗?
标准在哪里规定这种行为?