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

时间:2013-03-08 20:02:46

标签: 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;
}

有效。但现在我想使用v.reserve(n);代替(1)来提高支持它的类型的速度。但我仍然希望能够为不能编译reserve

的类型编译此代码

这是实现这个目标的简单方法吗?

我知道我可能会专注于硬编码类型,但它看起来并不好。

C ++ 11没问题。

3 个答案:

答案 0 :(得分:8)

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

Live example.有关解释,请查看here

答案 1 :(得分: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;
}

以下是 live example ,显示只使用未定义任何reserve()成员函数的UDT跳过对reserve()的调用。

答案 2 :(得分:2)

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

检测C ++ 03中是否存在fill成员函数:

void reserve(std::size_t)