调用函数,如果有,则忽略

Call function, if there is, ignore otherwise

本文关键字:如果 函数 调用      更新时间:2023-10-16

我现在想做一个模板,将一些元素推入向量和其他类型,支持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;
}

它的工作原理。但是现在我想提高使用v.reserve(n);而不是(1)支持它的类型的速度。但是我仍然希望能够为不能编译reserve

的类型编译这段代码

是否有一些简单的方法来实现这一点?

我知道我可以专门化硬编码类型,但这似乎不太好。

使用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;
}

生活的例子。

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;
}

下面是一个实时示例,显示了对reserve()的调用被一个不定义任何reserve()成员函数的UDT简单地跳过。

不太难....您需要编写一个trait来检测具有正确签名的保留成员函数的存在。有了这个工具,你有不同的方法,你可以写一个reserve_模板函数,它使用该特征来调度对reserve()或no-op的调用,并从// (1)调用它,或者你可以在helper或fill本身中使用SFINAE。我会尝试使用helper函数,因为fill中的大部分代码都是相同的。

检测void reserve(std::size_t)成员函数是否存在于c++ 03:

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);
};
相关文章: