C++ 调用函数,如果有,则忽略,否则忽略
现在我想制作一个模板,将一些元素推送到向量和其他类型,支持C++ 调用函数,如果有,则忽略,否则忽略,c++,templates,c++11,C++,Templates,C++11,现在我想制作一个模板,将一些元素推送到向量和其他类型,支持push_back操作符 我可以这样做 template<typename T> T fill(size_t n) { T v; //(1) for(size_t i = 0; i < n; ++i){ v.push_back(generate_some_how()); } return v; } 模板 T填充(尺寸\u T n){ 电视 //(1) 对于(尺寸i
push_back
操作符
我可以这样做
template<typename T>
T fill(size_t n) {
T v;
//(1)
for(size_t i = 0; i < n; ++i){
v.push_back(generate_some_how());
}
return v;
}
模板
T填充(尺寸\u T n){
电视
//(1)
对于(尺寸i=0;i
它起作用了。但是现在我想使用v.reserve(n)来提高支持它的类型的速度代码>而不是(1)
。但是我仍然希望能够为那些不会编译reserve
这是实现这一目标的简单方法吗
我知道我可能专门处理硬编码类型,但这似乎并不好
C++11还可以。不太难。。。。您需要编写一个trait,用正确的签名检测保留成员函数的存在。有了这个工具,就有了不同的方法,你可以编写一个reserve\uuu
模板函数,使用这个特性来分派对reserve()
的调用或一个no op,然后从//(1)
调用它,或者你可以在助手或fill
本身中使用SFINAE。我会尝试使用helper函数,因为fill中的大多数代码都是相同的
检测C++03中是否存在void reserve(std::size\u t)
成员函数:
template <typename T>
struct has_reserve {
typedef char yes;
typedef yes no[2];
template <typename U, U> struct ptrmbr_to_type;
template <typename U>
static yes& test(ptrmbr_to_type<void (T::*)(std::size_t),&U::reserve>*);
template <typename U> static no& test(...);
static const bool value = sizeof(test<T>(0))==sizeof(yes);
};
模板
结构具有\u保留{
typedef char是;
typedef是否[2];
模板结构ptrmbr_to_类型;
模板
静态是和测试(ptrmbr_至_类型*);
模板静态无测试(…);
静态常量布尔值=sizeof(测试(0))==sizeof(是);
};
使用C++11的简单示例:
template<class T>
auto maybe_reserve(T& v, size_t n, int)
-> decltype(v.reserve(n), void())
{
v.reserve(n);
}
template<class T>
void maybe_reserve(T&, size_t, long){}
template<typename T>
T fill(std::size_t n) {
T v;
maybe_reserve(v, n, 0);
for(size_t i = 0; i < n; ++i){
v.push_back(generate_some_how());
}
return v;
}
模板
自动备用(T&v、尺寸、内部)
->decltype(v.reserve(n),void())
{
v、 储备(n);
}
模板
空容量(T&,大小,长){
模板
T填充(标准尺寸){
电视
可能_储备(v,n,0);
对于(尺寸i=0;i
有关说明,请查看。C++11中的一种可能方法:
template<typename T, typename = void>
struct reserve_helper
{ static void call(T& obj, std::size_t s) { } };
template<typename T>
struct reserve_helper<T, decltype(std::declval<T>().reserve(0), void(0))>
{ static void call(T& obj, std::size_t s) { obj.reserve(s); } };
template<typename T>
T fill(std::size_t n)
{
T v;
reserve_helper<T>::call(v, 10);
for(std::size_t i = 0; i < n; ++i){
v.push_back(generate_somehow());
}
return v;
}
模板
结构保留辅助程序
{静态void调用(T&obj,std::size_T s){};
模板
结构保留辅助程序
{静态void调用(T&obj,std::size_T s){obj.reserve(s);};
模板
T填充(标准尺寸)
{
电视
reserve_helper::call(v,10);
对于(标准::大小\u t i=0;i
这里有一个显示对reserve()
的调用被UDT跳过,UDT没有定义任何reserve()
成员函数。我对此表示怀疑,但我不确定。我的猜测是,你将不得不使用模板专门化不太难。。。。您需要编写一个trait,用正确的签名检测reserve
成员函数的存在。有了这个工具,就有了不同的方法,你可以编写一个reserve\uuu
模板函数,使用这个特性来分派对reserve()
的调用或一个no op,然后从//(1)
调用它,或者你可以在助手或fill
本身中使用SFINAE。我想使用一个助手函数,因为大多数代码在<代码>填充< /代码>是相同的。如果你使用C++ 11,考虑支持适当的<代码> ESPOTE < /CUL>调用以替换<代码> PUBSURBACK/<代码>。有没有理由这样做,而不只是调用<代码> v.Reavy(n);std::generate_n(std::back_inserter(v),n,generate_some_how)代码>在呼叫站点?(除了删除一行代码)或者它也可以稍微优化一些:v.resize(n);std::generate_n(v.begin(),n,generate_some_how)
如果您希望使用std容器或符合std的容器,则应使用typename T::size\u type
而不是size\u T
也可以使用C++03版本,虽然更加复杂和限制。在更改resize
为deque
@RiaD的reserve
后没有编译:这是GCC 4.7的问题。Clang 3.2和GCC 4.8工作正常。GCC的错误可以通过将第一个重载的返回类型更改为decltype(v.reserve(n),void())
来解决。顺便说一句,您可以避免额外的伪参数吗?看到这个:)@Andy:可以,但是我想说清楚要求reserve
返回void
(是的,通常是这样,我知道)。:)@Xeo:好吧,好吧:)让我看看你有没有试着编译和运行这个3@Xeo:)太糟糕了3(提示:您正在“预订”10
,但通话后的容量为4
)