据我所知,基本类型是Scalar和Arrays是聚合的,但是用户定义的类型呢?我将以什么标准将它们分为两类?
struct S { int i; int j };
class C { public: S s1_; S s2_ };
std::vector<int> V;
std::vector<int> *pV = &v;
Run Code Online (Sandbox Code Playgroud) 以下代码在MSVC2010上编译并运行,是吗?
const std::string s = "foo";
std::string s2(std::move(s));
Run Code Online (Sandbox Code Playgroud)
我可以看出为什么这可能不会破坏任何东西,因为如果我采用s的内部我必须知道没有人会使用它所以我不得不放弃const.然而,编译器在ROM(在嵌入式应用程序中)实现const对象的位置呢?那么此举会变成副本吗?或者MSVC应该给我一个错误?
毫无疑问,很多人都熟悉Alexandrescus ScopeGuard先生模板(现在是Loki的一部分)和新版ScopeGuard11:http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012- 安德烈- Alexandrescu的系统性,错误处理-在-C
来源:https: //gist.github.com/KindDragon/4650442
在他在c ++和2012年以后的演讲中,他提到他无法找到一种方法来正确检测范围是否因异常而退出.因此,当且仅当由于异常而退出作用域时,他才能实现SCOPE_FAIL宏,该宏将执行提供的lambda(通常用于回滚代码).这将使得dismiss()成员函数不再需要,并使代码更具可读性.
既然我不像Alexandrescu先生那样天才或经验丰富,我希望实施SCOPE_FAIL并不像以下那么容易:
~ScopeGuard11(){ //destructor
if(std::uncaught_exception()){ //if we are exiting because of an exception
f_(); //execute the functor
}
//otherwise do nothing
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么不呢?
为了保存一些代码,我可以说我有一个名为的自定义分配器MyAlloc
,我已成功使用std::vector<int>
如下:
std::vector<int,MyAlloc<int>> vec;
Run Code Online (Sandbox Code Playgroud)
现在我想使用自定义分配器在std :: function中保存lambda,我该怎么做?
我失败的尝试:
int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
//...
});
Run Code Online (Sandbox Code Playgroud)
更新: std :: function中的分配器已被删除
我目前正在使用boost.parameter和一些工厂函数,编译时间越来越多.
目前我有一个像这样的共同模式:
auto thing = makeThing(property1 = foo::bar, "myThing"_thingName);
Run Code Online (Sandbox Code Playgroud)
其中makeThing
有30个参数,其中大部分都是默认值.我想保留"命名参数"语法以及按类型而不是按位置匹配参数的能力.
如何在不改变工厂调用站点的语法的情况下获得更好的编译速度?
注意:根据boost.MPL速度和强度速度之间的差异来判断,如果现代元编程技术用于boost.parameter等效,那么编译时应该至少有一个数量级的改进.
更新:这是我正在做的一个简略示例:在裸机嵌入式上下文中,我根据基于策略的类设计习惯用不同的外围设备抽象为复杂的模板类.每个类在编译时都会获取大量配置信息,并且只使用所需的功能(不能依赖优化器来去除未使用的东西,因为所有SFR交互都是可观察的,因此是不稳定的,因此不允许).
这些基于策略的类对于用户来说是非常丑陋的,并且如果大多数嵌入式用户在公共界面中看到<,那么我会使用boost.parameter创建一个性感的工厂,以便他们可以传递所有类型编码的愿望(像hana风格)我生成的类作为本地静态连接到所需的ISR并传回一个句柄.
namespace usb
{
BOOST_PARAMETER_NAME(hw)
BOOST_PARAMETER_NAME(vid)
BOOST_PARAMETER_NAME(pid)
BOOST_PARAMETER_NAME(device_class)
BOOST_PARAMETER_NAME(max_packet_ep0)
BOOST_PARAMETER_NAME(max_packet)
BOOST_PARAMETER_NAME(packet_pool_size)
BOOST_PARAMETER_NAME(device_description)
BOOST_PARAMETER_NAME(device_calss_description)
BOOST_PARAMETER_NAME(can_power_down)
BOOST_PARAMETER_NAME(stall_supported)
BOOST_PARAMETER_NAME(setup_packet_timeout)
//...
BOOST_PARAMETER_FUNCTION(
(usb_handle),
make,
tag,
(required(hw, *))
(optional
(vid, *, 0x6001_ci)
(pid, *, 0x1234_ci)
(device_class, *, cdc_class{})
(max_packet_ep0, *, 8_ci)
(max_packet, *, 64_ci)
(packet_pool_size, *, 12_ci)
(device_description, *, "")
(device_calss_description, *, "")
(can_power_down, *, 0_ci)
(stall_supported, *, 0_ci)
(setup_packet_timeout, *, 100_ci)
)
)
{
// makes a local …
Run Code Online (Sandbox Code Playgroud) 这是一个跟进的原因为什么Alexandrescu不能使用std :: uncaught_exception()在ScopeGuard11中实现SCOPE_FAIL?
我想检测是否有人MyClass
在另一个类的析构函数中创建(或者在调用堆栈中的某个地方使用了一个活动的析构函数).
class MyClass
{
public:
MyClass(){
assert(???what to put here????);
}
}
void f(){
MyClass m; //whether this asserts should be context dependant
}
class OtherClass{
~OtherClass(){
MyClass m; //this should assert
f(); //this should too;
}
}
int main()
{
MyClass m; //this should not assert
f(); //this should also not assert
}
Run Code Online (Sandbox Code Playgroud)
一次尝试可能是:
assert(!std::uncaught_exception());
Run Code Online (Sandbox Code Playgroud)
但是只有在因为异常而被调用析构函数时才会有效,而不是因为对象超出范围而被调用.
我有这样的结构:
template<typename... Ts>
struct List {}
typedef List<char,List<int,float,List<int,unsigned char>>,List<unsigned,short>> MyList;
Run Code Online (Sandbox Code Playgroud)
我想基本上把它压扁到一个列表.什么是最好的方法?如果我把它弄得足够长,我想我可以通过递归制作一些东西,但有些东西告诉我应该有更好的方法.
我想要的上述树的结果应该类似于:
typedef List<char,int,float,int,unsigned char,unsigned,short> FlattenedList;
Run Code Online (Sandbox Code Playgroud)
这是我的第一次尝试:
template<typename... Ts>
struct List{};
template<typename... Ts>
struct FlattenTree{
typedef List<Ts...> Type;
};
template<typename... Ts, typename... Us, typename... Vs>
struct FlattenTree<Ts...,List<Us...>,Vs...>{
typedef typename FlattenTree<Ts..., Us..., Vs...>::Type Type;
};
Run Code Online (Sandbox Code Playgroud)
但它会导致此错误: error C3515: if an argument for a class template partial specialization is a pack expansion it shall be the last argument
rici在这里指出MSVC2013在抱怨什么,所以这里没有编译错误:
§14.8.2.5(从类型中推导模板参数)第5段列出了无法推导出模板参数的上下文.相关的是列表中的最后一个:
— A function parameter pack that does not occur at …
Run Code Online (Sandbox Code Playgroud) constexpr uint32_t BitPositionToMask(int i,int Size){
static_assert(i < Size,"bit position out of range");
return 1 << i;
}
Run Code Online (Sandbox Code Playgroud)
这会产生:
error: non-constant condition for static assertion
Run Code Online (Sandbox Code Playgroud)
在GCC 4.6.2我没有得到什么或这是一个GCC错误?
更新: 谢谢Andy再次成为我的书呆子守护天使.因为我在编译时有值,所以我只是把它作为模板,它按预期工作.
template<int i,int Size>
constexpr uint32_t BitPositionToMask(){
static_assert(i < Size,"bit position out of range");
return 1 << i;
}
Run Code Online (Sandbox Code Playgroud) 如果我希望模板模板参数有一个争论,那么我可以声明如下:
template<template<typename> class T>
struct S {
T<int> t_;
//other code here
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我以后想要提供一个模板模板参数,该参数需要两个参数,其中第二个具有默认值(如std :: vector)T<int> t_;
仍然有效,但模板不匹配template<typename> class T
.我可以通过制作template<typename> class T
一个可变参数模板模板来解决这个问题template<typename...> class T
.现在我的代码更灵活了.
我将来可以将所有模板模板参数变为可变参数吗?有什么理由我不应该(因为其他原因我的代码已经需要C++ 11支持)?
我知道这是未定义的行为:
int i = 0;
int a[4];
a[i] = i++; //<--- UB here
Run Code Online (Sandbox Code Playgroud)
因为i
左手侧和右手侧的评估顺序是不确定的(这;
是唯一的序列点).
把这个推理更进一步,在我看来,这将是 未定义 未指明的行为:
int i = 0;
int foo(){
return i++;
}
int main(){
int a[4];
a[i] = foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
尽管在=
我理解的情况下,在右侧有一些序列点仍然存在未定义未指定是否f()
或a[i]
首先评估.
我的假设是否正确?当我在作业的左侧使用全局或静态变量时,我是否必须小心谨慎,右手在任何情况下都不会修改它?