关于c ++:调用函数,如果有,则忽略

Call function, if there is, ignore otherwise

本问题已经有最佳答案,请猛点这里访问。

我现在想制作模板,将一些元素推送到向量和其他类型,这些类型支持push_back操作符。

我可以这样做

1
2
3
4
5
6
7
8
9
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是可以的。


使用C++ 11的一个简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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中的一种可能方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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跳过。


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

检测是否在C++ 03中存在EDCOX1×4成员函数:

1
2
3
4
5
6
7
8
9
10
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);
};