如果标题不合适,请随时重新标注。我试图在STL中找到find和find_if算法之上的包装器。这就是我现在所拥有的。
template<typename Type, size_t SIZE>
int IndexOf(const Type(&arr)[SIZE], const Type& val)
{
return IndexOf( arr, arr + SIZE, val);
}
template<typename Iter, typename Type>
int IndexOf(Iter first, Iter last, const Type& val)
{
auto index = find(first, last, val);
if ( index != last)
{
return distance(first, index);
}
return -1;
}
template<typename Type, size_t SIZE, typename Pred>
int IndexOf(const Type(&arr)[SIZE], Pred pred)
{
return IndexOf(arr, arr + SIZE, pred);
}
template<typename Iter, typename Pred>
int IndexOf(Iter first, Iter last, Pred pred)
{
auto index = find_if(first, last, pred);
if ( index != last)
{
return distance(first, index);
}
return -1;
}
以下用法无法编译说不明确的重载。
vector<string> names;
names.push_back("Jagan");
names.push_back("Gagan");
names.push_back("Magan");
names.push_back("Pagan");
names.push_back("Vagan");
std::cout << "Index of (Gagan)" << IndexOf(begin(names), end(names),
[](const string& name)
{
return name == "Gagan";
});
以上示例用法仅用于简洁。
答案 0 :(得分:3)
按照stdlib的做法:不要超载。例如,stdlib提供了两个函数,可以让您搜索范围内的某些内容。
一个名为find
(如“找到该值!”),另一个名为find_if
(如“如果谓词返回true,则为”!)。
另一个选择可能是采用一些SFINAE技巧(使用C ++ 11和表达式SFINAE):
template<class T>
T create();
template<class InIt, class T>
auto find(InIt first, InIt last, T const& value)
-> decltype((*first == value), create<InIt>())
{
// ...
}
如果*first == value
不是有效表达式,则此函数将从重载集中删除(通常不将谓词存储在容器中并使用相同的谓词进行搜索)。
, create<InIt>()
中的decltype
是为其提供InIt
的返回类型。 create
未定义,因为它只会在未评估的上下文中使用,因此不需要定义(这使生活更容易,我们不必猜测我们如何实际构建这样的对象。我们只需取类型InIt
)。如果我使用first
而不是create<InIt>()
,则返回类型将为InIt&
,这会有点令人惊讶且不好,因为您返回对局部变量的引用
template<class Init, class Pred>
auto find(InIt first, InIt last, Pred pred)
-> decltype((pred(*first)?0:0), create<InIt>())
{
// ...
}
如果pred(*first)
不是有效表达式,则此函数将从重载集中删除,即pred
不会将value_type
InIt
作为参数。如果pred
的{{1}}的返回类型未明确转换为operator()
,则会通过使用bool
(三元逻辑运算符)进行测试。同样,?:
用于为函数提供, create<InIt>()
返回类型。
这是针对您具体案例的small live example on Ideone。请注意,我在此处未使用InIt
,因为文字create<int>()
已经是0
类型。
答案 1 :(得分:0)
这是一种消除两个重载歧义的方法:如果迭代器的值类型可以从参数构造,我们选择find
,否则我们将参数视为谓词:
#include <algorithm>
#include <iterator>
#include <type_traits>
template<typename Iter>
int IndexOf(Iter first, Iter last, typename std::iterator_traits<Iter>::value_type const & val)
{
auto index = std::find(first, last, val);
return index != last ? std::distance(first, index) : -1;
}
template<typename Iter, typename Pred>
typename std::enable_if<!std::is_constructible<typename std::iterator_traits<Iter>::value_type, Pred>::value, int>::type
IndexOf(Iter first, Iter last, Pred pred)
{
auto index = std::find_if(first, last, pred);
return index != last ? distance(first, index) : -1;
}