17

我现在想制作将一些元素推送到支持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 没问题。

4

3 回答 3

11

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

活生生的例子。有关解释,请查看此处

于 2013-03-08T20:18:12.293 回答
6

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 跳过。

于 2013-03-08T20:20:26.907 回答
2

不太难......你需要编写一个特征来检测具有正确签名的保留成员函数的存在。使用该工具,您可以使用不同的方法,您可以编写一个reserve_模板函数,该函数使用该特征调度到调用reserve()或无操作并从中调用它,// (1)或者您可以在帮助程序或fill本身中使用 SFINAE。我会尝试使用辅助函数,因为填充的大多数代码都是相同的。

检测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);
};
于 2013-03-08T20:09:12.057 回答