调用函数,如果有,则忽略
问题描述:
我现在想要制作模板,它将一些元素推送到向量和其他类型,支持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;
}
Live example.有关解释,看一看here。
答
不太难....你需要写一个特征来检测预留成员函数的存在与正确的签名。使用该工具有不同的方法,您可以编写一个reserve_
模板函数,使用该特性分派到reserve()
的调用或no-op并从// (1)
调用它,或者您可以在帮助程序中使用SFINAE或fill
本身。我会尝试使用辅助函数,因为填充中的大部分代码都是相同的。
检测是否void reserve(std::size_t)
构件函数存在于C++ 03:使用C++ 11
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);
};
答
在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()
被简单地与没有定义任何reserve()
构件功能的UDT跳过。
我怀疑它,但我不确定。我的猜测是你将不得不使用模板专门化 – 2013-03-08 20:05:34
不太难......你需要编写一个特征来检测具有正确签名的'reserve'成员函数的存在。有了这个工具,你可以使用不同的方法,你可以编写一个'reserve_'模板函数,使用这个特性分派给'reserve()'或者一个no-op的调用,并从//调用它)'或者你可以在助手或者'fill'中使用SFINAE。我会尝试使用辅助函数,因为'fill'中的大部分代码都是相同的。 – 2013-03-08 20:07:00
如果您使用的是C++ 11,请考虑支持适当的'emplace'调用来替换'push_back'。 – 2013-03-08 20:20:41