我正在使用一个带有一组整数的模板化类.代码就像,
template<unsigned... Idx>
struct work{ ... };
Run Code Online (Sandbox Code Playgroud)
然后我意识到,用户可能需要提供一组整数或一系列整数.所以,我改变了语法,以支持实例化,如,
work<indexes<1,3,2,4> > //instead of work<1,3,2,4>
work<span<1,4> > //same as work<1,2,3,4>
Run Code Online (Sandbox Code Playgroud)
同时,在C++,我们有大量的运营商,并且可以被用于配制异国表达式模板(比方说boost::xpressive
,boost::lambda
,boost::spirit
等等),用于类型操纵可能性要少得多.
在Sean Parent的一个boostcon主题演讲中,他指出一个仍然不能写pair<int>
的表示a pair of integers
.在我的persinal库中,我做了一个语法,就像tuple<int[3]>
表示一个3个整数的元组,而不是在类型参数中写一个带有3个int的元组,注意到我没有在任何地方写一个原始数组作为元组参数!(注意:std::array<int,3>
与上面不一样,因为std :: array不能存储引用,tuple
可以说std::tuple<int&,int&,int&>
,可以)
所以,我想知道我能写的不同类型的"类型表达式"是什么?
到目前为止,我可以想到对象类型,函数类型,引用类型,有/无cv修饰符,指针等
template<class T>
struct tpl;
using t1 = tpl<int>;//simple type
//function (can have function pointer/reference also)
// e.g. void(*)(int,float) or void(&)(int,float)
using t2 = tpl<void(int,float)>;
//array can have pointer / reference also
//e.g. int(&)[4] or …
Run Code Online (Sandbox Code Playgroud) 很久以前我看过一个非递归实现来从类型序列/值序列中获取最后一个值/类型.它有一个很好的属性,实例化的模板数量是序列包含的元素数量的独立(和常量).
实现很简单,如下所示
// a struct that eats anything and everything
struct eat { template<class T> eat(T&&) {} };
// generates V matching with U
template<class U, class V> struct match { using type = V; };
template<class... X> struct back_
{
template<class U>
static U&& get(typename match<X, eat>::type..., U&& u)
{
return static_cast<U&&>(u); // forward
}
};
// simple macro to avoid repetition for trailing return type.
#define RETURNS(exp) -> decltype(exp) { return exp; }
// get the last value …
Run Code Online (Sandbox Code Playgroud) 我对c ++隐式复制构造函数的理解类似于
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
Run Code Online (Sandbox Code Playgroud)
移动构造函数,复制和移动赋值也遵循类似的模式.
为什么没有定义类似于以下内容?
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
Run Code Online (Sandbox Code Playgroud)
例
我有一个类具有隐式复制/移动构造函数/赋值运算符,以及一些转换构造函数.我把工作委托给了一些实现类.
class common_work //common implementation of many work like classes
{
common_work(common_work const&) = default;
common_work(common_work&&) = default;// ... implicit constructors work for me.
//a forwarding constructor which can take many work like objects
template<class T, enable_if<work_like<T> > >
common_work(T&& x) { ... }
};
class work1 //one of the implementation …
Run Code Online (Sandbox Code Playgroud) c++ constructor assignment-operator perfect-forwarding c++11
std :: tr1 :: aligned_storage的基本用法是什么?它可以用作数据类型Foo的自动存储器,如下所示吗?
struct Foo{...};
std::tr1::aligned_storage<sizeof(Foo)
,std::tr1::alignment_of<Foo>::value >::type buf;
Foo* f = new (reinterpret_cast<void*>(&buf)) Foo();
f->~Foo();
Run Code Online (Sandbox Code Playgroud)
如果是这样,那么在buf中存储多个Foo就像,
std::tr1::aligned_storage<5*sizeof(Foo)
,std::tr1::alignment_of<Foo>::value >::type buf;
Foo* p = reinterpret_cast<Foo*>(&buf);
for(int i = 0; i!= 5; ++i,++p)
{
Foo* f = new (p) Foo();
}
Run Code Online (Sandbox Code Playgroud)
他们是有效的计划吗?它还有其他用例吗?Google搜索只会生成有关aligned_storage的文档,但关于它的使用情况却很少.
在c ++ 11中,我们为对象提供了很好的统一初始化语法.为什么它不扩展到初始化非对象类型?
这有什么语法歧义,还是我问的一些愚蠢的问题?
例:
struct s{ int k;};
s s1{1}; //ok (object initialization)
s const& s3{3}; //ok (object initialization)
s& s2{s1}; //error (reference initialization)
Run Code Online (Sandbox Code Playgroud)
一个更有用的例子:
struct t{ t(t const& x) : k(x.k){} int k;};
struct c
{
c(t& x1,t& x2)
: s1_{x1} //error (reference initialization)
, s2_{x2} //ok (object initialization)
{}
t& s1_;
t s2_;
};
Run Code Online (Sandbox Code Playgroud)
另一个 :
template<class T>
T get()
{
return T{};
}
//ok (object initialization)
get<int>();
//error (void initialization? I do not know terminology for …
Run Code Online (Sandbox Code Playgroud) 最近,当我在代码中更改了某些容器,分配器时,我遇到了很多typedef和不完整类型的问题.
我之前有过的
struct foo;//incomplete type.
typedef std::vector<foo> all_foos;
typedef all_foos::reference foo_ref;
Run Code Online (Sandbox Code Playgroud)
虽然不完全不确定上述行是否合法,但这适用于我使用的每个实现.当我以为我可以完成这项工作时std::tr1::array
,改变了以上两行
typedef std::tr1::array<foo,5> all_foos;
typedef all_foos::reference foo_ref;
Run Code Online (Sandbox Code Playgroud)
这里的一切都中断了,因为编译器试图实例化array
并且因为foo
类型不完整而失败.我所需要的是foo
对数组的"其他部分"的引用,而不是很感兴趣.当我创建这样的数组时,foo肯定会完全可用.
当typedef std::allocator<foo>::pointer foo_ptr
被typedef替换时,同样的问题stack_alloc<foo,10>::pointer foo_ptr
.其中,stack_alloc
实现像
template<typename T,unsigned N>
struct stack_alloc
{
typedef T* pointer;
typedef std::tr1::aligned_storage<sizeof(T)*N, std::tr1::alignment_of<T>::value> buffer;
};
Run Code Online (Sandbox Code Playgroud)
假定该,value_type
,pointer
,reference
,iterator
等不依赖于的完整性T
,以及明知类不能没有完全类型实例化,类型定义怎么这么能在独立于特定的容器或分配器的通用方式进行?
注意:
vector
而不是替换它std::array
,尽管问题仍然存在.stack_alloc
代码远未完成,只显示问题的一部分.all_foos
不完整类型的对象foo
.struct foo{ foo_ptr p;};
无法定义.虽然可能 …有几次我在一个vector
或另一个可变序列(序列适配器)上使用受限制的接口,它只允许push_back
和clear
.它有一些很好的属性,例如,迭代器可以基于索引来设计,索引总是稳定的(比如stable_vector
但也有元素连续性),因此可以存储而不用担心失效,除非它被清除.
我想用一个适配器类来代替vector
或其他序列直接强调接口(以及防止使用不支持的操作,如任何意外的错误insert
,erase
等等).
是否存在与此append_only
序列匹配的现有ADT ?否则任何人都可以推荐这个序列适配器的合适名称?
我正在研究一种主要使用C++作为其核心组件的产品.虽然它使用Visual C++作为Windows平台的主要编译器及其编辑器和调试器作为主要开发环境,但未使用任何Microsoft特定技术.对于其他平台,它使用gcc进行编译.
我的代码库大量使用模拟的右值引用(使用Boost移动库),可变参数模板(使用Boost处理器),在某些情况下使用表达式模板.
我很想转换到C++ 11来获得更清晰的代码库,使用rvalue引用,完美转发,默认和删除构造函数,可变参数模板以及auto和decltype.
如果我这样做,我可能会对现有代码进行一些修改以简化它(使用模板别名和constexpr).在这种情况下,我必须使用mingw切换到Windows平台的gcc,因为Visual Studio没有默认和删除的实现,以及可变参数模板.另外,我必须切换到gdb作为调试器和不同的代码编辑器.
对我来说,代码简单性和性能方面的好处看起来很大,但稳定性,可用性(在某些平台上如Android),调试(从Visual Studio迁移到gdb,因为我们有许多为Visual Studio调试器开发的可视化工具)和代码编辑器(对于大量的模板代码而言,我没有太多使用自动完成,重构等,而Codelite,Codeblocks,QtCreator与我们的构建系统配合良好)是一些问题.
我想知道是否有任何中型/大型项目(商业或开源)使用/打算使用上述任何C++ 11功能?这种迁移需要多少努力?
任何实践经验,技巧或智慧的话语都会帮助我做出决定.
我对异常处理的理解非常有限.虽然我发现很容易抛出异常(或者我可以将它打包expected<T>
用于以后的消费),但我对如何处理异常几乎一无所知.
目前我的知识仅限于
清理我自己的资源并重新抛出要在适当位置处理的异常.例如
ptr p = alloc.allocate(n);
try
{
uninitialized_copy(first,last,p);//atomic granularity, all or none
}
catch(...)
{
alloc.deallocate(p,n);
throw;
}
Run Code Online (Sandbox Code Playgroud)但我想,这可以在一个RAII
模式中等效地转换为
alloc_guard<ptr> p{alloc.allocate(n)};
uninitialized_copy(first,last,p.get());
p.commit();
Run Code Online (Sandbox Code Playgroud)
在顶层捕获异常,撰写并打印一条好消息并退出.eg
int main(int argc,char** argv)
{
try
{
app_t the_app(argc,argv);
the_app.run();
}
catch(std::runtime_error& e)
{
//instead of what, I can also compose the mesage here based on locale.
std::cout<<e.what()<<std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)所以,我所做的就是处于顶级功能,例如main
捕获异常并打印相应的消息并关闭.
在使用各种外部库作为实现的后端实现具有一组良好API的库时,我意识到第三方库异常是我的API规范的一部分,因为它们跨越我的库边界并落在用户代码中!
因此,我的库API泄露了我用于用户代码的外部库(并且每个库都有自己的异常层次结构)的所有异常.
这导致了我的问题,当我发现任何异常时可以做些什么?
进一步来说,
mpl::map
)吗?file_not_found
或者disk_error
,用另一个文件重新运行该函数)?谢谢
我知道,给定一个初始化转发/通用引用的表达式,就可以推断出lvalues是type,T&
而rvalues是type T
(而不是T&&
)。
因此,为了只允许右值,需要写
template<class T, enable_if<not_<is_lvalue_reference<T> >,OtherConds... > = yes>
void foo(T&& x) {}
Run Code Online (Sandbox Code Playgroud)
并不是,
template<class T, enable_if<is_rvalue_reference<T>,OtherConds... > = yes>
void foo(T&& x) {}
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么对于转发引用,右值被推导为类型T
而不是T&&
?我猜想,如果推论为,T&&
则相同的引用折叠规则也与T&& &&
相同T&&
。
c++ templates perfect-forwarding c++11 template-argument-deduction
c++ ×10
c++11 ×7
templates ×3
constructor ×1
containers ×1
exception ×1
recursion ×1
sequence ×1
template-argument-deduction ×1
try-catch ×1
typedef ×1