我始终认为私有继承仅仅意味着类型不会告诉外部它是从某个基类继承的。不过,似乎还有更多的限制。
考虑以下最小示例:
struct MyInterface {};
struct MyImpl : private MyInterface {};
struct Inherited : public MyImpl {
// Error: 'MyInterface' not accessible because 'MyImpl' uses 'private' to inherit from 'MyInterface'
void doSomething(MyInterface* mi) {}
};
struct Noninherited {
// All fine!
void doSomething(MyInterface* mi) {}
};
Run Code Online (Sandbox Code Playgroud)
Clang、GCC 和 MSVC 都拒绝此代码。鉴于我之前的假设,我本以为一切都会好起来的。
doSomething只是需要一个指向 的指针MyInterface,但它不会告诉外界其继承层次结构中Inherited有哪些MyInterface内容。在我看来,私有继承不仅不告诉外界继承结构,反而使整个继承结构完全“忘记”继承类型的存在。
这是理解私有继承的正确“思维模型”吗?还有其他意想不到的限制吗?
的std::coroutine_handle是C ++ 20的新协程的一个重要部分。例如,发电机经常(总是?)使用它。在我见过的所有示例中,在协程的析构函数中手动销毁句柄:
struct Generator {
// Other stuff...
std::coroutine_handle<promise_type> ch;
~Generator() {
if (ch) ch.destroy();
}
}
Run Code Online (Sandbox Code Playgroud)
这真的有必要吗?如果是的话,为什么没有这个已经被完成的coroutine_handle,是有一个RAII版本coroutine_handle,其行为这种方式,并会如果我们忽略了发生什么destroy电话?
例子:
std::coroutine_handle。Cppreference文档包含 5个stdfloat新类型:float16_t、float32_t、float64_t和float128_t。bfloat16_t虽然前 4 种类型是不言自明的(分别是 16、32、64 和 128 位的浮点数),但最后一种类型bfloat16_t对我来说根本不清楚。这个类型代表什么?它的名字中的是什么b意思?
我目前正致力于编写池分配器.我的问题归结为以下代码:
template <typename T>
union myUnion {
T data;
myUnion<T>* nextUnion;
};
void someFunction(){
myUnion<T> mu;
T* t = new (std::addressof(mu.data)) T();
//some code
myUnion<T>* mu2 = reinterpret_cast<myUnion<T>*>(t);
}
Run Code Online (Sandbox Code Playgroud)
mu的地址是否与mu2相同?
关键字constexpr在引入 C++11 标准时对其函数实施了相当严格的限制。C++14 和 C++20 放宽了这些限制(最值得注意):
return语句static_assert等。try并且asmC++23 进一步软化了这些限制。从我在cppreference中看到的,constexprfor函数似乎只剩下以下含义:
C++23 甚至删除了 constexpr 函数必须在编译时对于p2448r2中的任何类型“可计算”的限制。根据我的理解,这完全消除了constexpr在编译时评估函数的想法。
是这样吗?如果是这样,constexpr函数还有什么用处呢?
我目前正在学习 vulkan。在其中一个教程中,我看到了一个大致执行以下操作的函数:
#define SOMESTRING "Hello World!"
std::vector<const char*> buildVector() {
std::vector<const char*> vec;
vec.push_back(SOMESTRING);
return vec;
}
Run Code Online (Sandbox Code Playgroud)
当我看到这个时,我想知道:这是定义的行为吗?字符串的内容不是"Hello World!"位于堆栈上,因此一旦函数返回就无效吗?如果这是未定义的行为,那么正确的方法是什么?不幸的是,std::string由于 vulkan API ,使用不是一种选择。
我正在研究C++ 17的新功能.我偶然发现了N4266这个功能,它说现在枚举和名称空间也可以使用属性.不同消息来源称,Visual Studio 2017已经完全支持此功能.我用[[deprecated]]属性编写了一个测试.对于名称空间,这非常有效.但是,没有为枚举生成警告.我的实施中有错误吗?我错过了什么?
enum MyEnum
{
val = 0,
vaal[[deprecated]] = val
};
void test()
{
MyEnum e = MyEnum::vaal; //Should emit Warning, but does not
MyEnum e2 = MyEnum::val; //No Warning
}
Run Code Online (Sandbox Code Playgroud)
我正在使用Visual Studio Community 2017版本15.3.5.这说明自VS2015以来它应该得到支持./ std:使用c ++ 17.
这也说明这应该是正确的语法.
如果我使用枚举或枚举类没有区别.
预先说明:我知道在这里做我所要求的不是一个好主意。这只是来自病态语言好奇心的问题,而不是实际使用中的问题。我在这里应用的规则完全是任意的。
假设我们有一个完全定义如下的函数。它不得更改为除此之外的任何内容,不允许模板或函数重载。这个函数的实现也不能改变(并且可以被视为未知)。然而,我们知道该参数用作输出参数。
void my_func(int (&arr)[10]);
Run Code Online (Sandbox Code Playgroud)
在另一个函数中,我们动态分配一个数组。这个分配也不能改变,我们不允许在栈上分配。也不允许进一步分配。
int* my_arr = new int[10];
Run Code Online (Sandbox Code Playgroud)
是否有可能以某种方式调用my_func并传递它my_arr?换句话说,是否有可能以某种方式欺骗类型系统将其my_arr视为数组而不是指针?
朴素的铸造不能解决问题,所有这些都会导致编译错误:
my_func((int[10])my_arr);
my_func(static_cast<int[10]>(my_arr));
my_func(reinterpret_cast<int[10]>(my_arr));
Run Code Online (Sandbox Code Playgroud)
另一个注意事项:我想欺骗类型系统。我不想从堆栈数组等复制数据。为什么?再次:病态的好奇心。
英特尔内在函数的名称中内置了向量的子类型。例如,_mm_set1_ps是 a ps,即packed single-precisionaka。A float。尽管它们中的大多数的含义是明确的,但它们的“全名”packed single-precision从功能描述中并不总是清晰的。我创建了下表。不幸的是,有些条目丢失了。它们有何价值?其他问题见表下方。
| 缩写 | 全名 | C/++ 等效项 |
|---|---|---|
| 附注 | 压缩单精度 | 漂浮 |
| 酸碱度 | 压缩半精度 | 没有任何** |
| PD | 压缩双精度 | 双倍的 |
| 个人电脑 | 压缩半精度复数 | 没有任何** |
| pi8 | ??? | int8_t |
| PI16 | ??? | int16_t |
| pi32 | ??? | int32_t |
| Epi8 | ??? | int8_t |
| 表观16 | ??? | int16_t |
| 表观32 | ??? | int32_t |
| 表观64 | ??? | int64_t |
| 外延64x | ??? | int64_t |
附加问题:
epiX和 和有什么区别piX?pi64存在?epi64和 和有什么区别epi64x?** 我发现了这个,但似乎没有标准方法来表示 C/++ 中的半精度(复数)值。如果这有任何改变,请纠正我。
在vulkan中,有一个结构是管道创建所需的,命名为VkPipelineRasterizationStateCreateInfo.在这个结构中有一个名为的成员rasterizerDiscardEnable.如果将此成员设置为,VK_TRUE那么在光栅化步骤之前将丢弃所有基元.这会禁用帧缓冲区的任何输出.
我想不出这可能有意义的场景.在哪些情况下它可能有用吗?