我必须承认,我不明白什么是真正的目的,polymorphic_allocator
何时/为什么/如何使用它.
例如,pmr::vector
具有以下签名:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
Run Code Online (Sandbox Code Playgroud)
什么是polymorphic_allocator
要约?std::pmr::vector
对老式的提供有什么好处std::vector
?我现在能做什么才能做到现在为止?
分配器的真正目的是什么?我应该何时使用它?
std::is_pod
可能会在C++ 20中弃用.
这个选择的原因是什么?我应该用什么来代替std::is_pod
知道某种类型是否真的是POD?
从[5.3.3/1]开始,我发现:
sizeof运算符不应用于具有函数或不完整类型的表达式
从[3.9/5]我发现:
不完全定义的对象类型和cv void是不完整的类型
无论如何,因为sizeof
不评估它的操作数,我会说这sizeof(void())
是一个合法的表达式(实际上GCC编译它,结果是1).
另一方面,从这里开始,void
在讨论sizeof
时没有提及,既没有提到具有大小1的类型,也没有提到具有实现定义大小的类型的列表.
因此问题是:是sizeof(void())
一种法律表达吗?
是否保证大小等于1?
或者这是一个导致UB的法律表达,这就是全部?
考虑以下课程:
struct S { ~S() = delete; };
Run Code Online (Sandbox Code Playgroud)
很快就问题的目的:我无法创建S
类似的实例,S s{};
因为我无法销毁它们.
正如评论中所提到的,我仍然可以创建一个实例S *s = new S;
,但我也无法删除它.
因此,我可以看到删除析构函数的唯一用法是这样的:
struct S {
~S() = delete;
static void f() { }
};
int main() {
S::f();
}
Run Code Online (Sandbox Code Playgroud)
也就是说,定义一个只暴露一堆静态函数的类,并禁止任何创建该类实例的尝试.
删除的析构函数的其他用途(如果有的话)是什么?
从cppreference,我发现:
类模板std :: function是一个通用的多态函数包装器.std :: function的实例可以存储,复制和调用任何Callable目标 - 函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针.
我不明白为什么一个std::function
应该能够存储这样的指针,我以前从未听说过这个功能.
它是否真的可能,我错过了某些内容或文档中的错误?
operator()
在这种情况下应该怎么做?
从文档中可以看出:
使用参数args调用存储的可调用函数目标.
无论如何,这里没有存储的可调用函数目标.我错了吗?
说实话,我甚至无法弄清楚这个函数的正确语法是什么,否则我会写一个例子来测试它.
如何使用以下模板来定义指向数据成员的指针?
template< class R, class... Args >
class function<R(Args...)>
Run Code Online (Sandbox Code Playgroud) 这是这个问题的后续行动.
评价和在回答据说超过一次,更多的void{}
是没有一个有效的类型-ID,也不是一个有效的表达式.
这很好,它是有道理的,这就是全部.
然后我通过工作草案的[7.1.7.4.1/2](占位符类型扣除).
有人说:
[...]
- 对于使用return
包含占位符类型的返回类型声明的函数中发生的非丢弃 语句,T
是声明的返回类型,并且e
是return
语句的操作数 .如果return
语句没有操作数,那么e
是void{}
;
[...]
那么,void{}
(概念上)合法与否?
如果它在工作草案中提到是可接受的(尽管只是作为- 如果它是一个 -陈述),它必须是合法的.这意味着它也decltype(void{})
应该是有效的,作为一个例子.
否则,工作草案应该使用void()
而不是void{}
?
嗯,说实话,我很确定我没有足够的技巧来指出工作草案中的错误,所以真正的问题是:我的推理出了什么问题?上面的子弹中提到了
什么void{}
,以及为什么在这种情况下它是一个法律表达?
如果参数列表必须位于参数列表的末尾,如果后者绑定到类,则不会得到参数列表的原因,如果参数列表是成员方法声明的一部分,则放宽约束.
换句话说,这个编译:
class C {
template<typename T, typename... Args, typename S>
void fn() { }
};
Run Code Online (Sandbox Code Playgroud)
以下不是:
template<typename T, typename... Args, typename S>
class C { };
Run Code Online (Sandbox Code Playgroud)
为什么第一种情况是正确的,第二种情况不是?
我的意思是,如果它是合法的语法,那么在这两种情况下都不应该这样吗?
要清楚,真正的问题是我正在定义一个类似于下面的类:
template<typename T, typename... Args, typename Allocator>
class C { };
Run Code Online (Sandbox Code Playgroud)
将分配器类型作为最后一种类型将不胜感激,但我可以以某种方式解决它(无论如何,如果你有一个建议,它的赞赏,也许你的优雅比我的更优雅!).
那就是说,我收到了错误:
参数包'Args'必须位于模板参数列表的末尾
所以,我只是很好奇地完全理解为什么它在某些情况下被接受,但它不在其他一些情况下.
这是一个类似的问题,但它只是解释了如何解决问题,这对我来说非常清楚.
由于第三方库的布局,我有类似下面的代码:
struct Base
{
static void SomeStaticMethod(){}
};
struct Derived1: private Base {};
struct Derived2: public Derived1 {
void SomeInstanceMethod(){
Base::SomeStaticMethod();
}
};
int main() {
Derived2 d2;
d2.SomeInstanceMethod();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在使用MSVC获得编译器错误C2247:
Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承.
我知道我不能访问Base
从成员Derived2
通过继承,因为私人符,但我仍然应该能够调用静态方法Base
-无论之间的继承关系Base
和Derived2
.
如何解决歧义并告诉编译器我只是调用静态方法?
这可能是一个基本问题,但我现在无法看到自己的反应.
请考虑以下代码:
template<bool b>
struct T {
static constexpr int value = (b ? 42 : 0);
};
template<bool b>
struct U {
enum { value = (b ? 42 : 0) };
};
int main() {
static_assert(T<true>::value == 42, "!");
static_assert(T<false>::value == 0, "!");
static_assert(U<true>::value == 42, "!");
static_assert(U<false>::value == 0, "!");
}
Run Code Online (Sandbox Code Playgroud)
我习惯使用类似的结构T
,但我不止一次看过U
用于相同目的的结构(主要是特征定义).
据我所知,它们都是在编译时解决的,它们解决了几乎相同的问题,但在我看来,它T
比可读性更强U
(我知道,我个人意见).
我的问题非常简单:有哪种技术原因可以解决哪一种解决方案比另一种更好?
更有甚者,其中一个不是一个可行的解决方案吗?
c++ ×10
c++11 ×5
void ×3
c++17 ×2
allocator ×1
constexpr ×1
data-members ×1
decltype ×1
destructor ×1
enums ×1
sizeof ×1
std-function ×1
stl ×1
templates ×1
type-traits ×1