Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调用函数,如果有,则忽略,否则忽略_C++_Templates_C++11 - Fatal编程技术网

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