我想检查向量中是否存在元素。我知道下面的代码将对其进行检查。
#include <algorithm>
if ( std::find(vector.begin(), vector.end(), item) != vector.end() )
std::cout << "found";
else
std::cout << "not found";
但是我有任何类型的向量。即std::vector<std::any>
我正在将元素推入这样的向量中。
std::vector<std::any> temp;
temp.emplace_back(std::string("A"));
temp.emplace_back(10);
temp.emplace_back(3.14f);
因此,我需要确定向量中是否存在字符串“ A”。 std :: find可以在这里帮助吗?
到目前为止,我正在使用下面的代码来做到这一点
bool isItemPresentInAnyVector(std::vector<std::any> items, std::any item)
{
for (const auto& it : items)
{
if (it.type() == typeid(std::string) && item.type() == typeid(std::string))
{
std::string strVecItem = std::any_cast<std::string>(it);
std::string strItem = std::any_cast<std::string>(item);
if (strVecItem.compare(strItem) == 0)
return true;
}
else if (it.type() == typeid(int) && item.type() == typeid(int))
{
int iVecItem = std::any_cast<int>(it);
int iItem = std::any_cast<int>(item);
if (iVecItem == iItem)
return true;
}
else if (it.type() == typeid(float) && item.type() == typeid(float))
{
float fVecItem = std::any_cast<float>(it);
float fItem = std::any_cast<float>(item);
if (fVecItem == fItem)
return true;
}
}
return false;
}
答案 0 :(得分:4)
我猜这应该很好:
#include <vector>
#include <string>
#include <any>
#include <algorithm>
#include <iostream>
int main(){
std::vector<std::any> temp;
temp.emplace_back(std::string("A"));
temp.emplace_back(10);
temp.emplace_back(3.14f);
int i = 10;//you can use any type for i variable and it should work fine
//std::string i = "A";
auto found = std::find_if(temp.begin(), temp.end(), [i](const auto &a){
return typeid(i) == a.type() && std::any_cast<decltype(i)>(a) == i;
} );
std::cout << std::any_cast<decltype(i)>(*found);
}
或者使代码更加通用和可重用:
#include <vector>
#include <string>
#include <any>
#include <algorithm>
#include <iostream>
auto any_compare = [](const auto &i){
return [i] (const auto &val){
return typeid(i) == val.type() && std::any_cast<decltype(i)>(val) == i;
};
};
int main(){
std::vector<std::any> temp;
temp.emplace_back(std::string("A"));
temp.emplace_back(10);
temp.emplace_back(3.14f);
//int i = 10;
std::string i = "A";
auto found = std::find_if(temp.begin(), temp.end(), any_compare(i));
std::cout << std::any_cast<decltype(i)>(*found);
}
重要说明:由于对std::any
类型的标准要求,因此保证只能在单个翻译单元中工作(例如,相同的类型不需要在不同的翻译单元中具有相同的类型标识符)
答案 1 :(得分:2)
不幸的是,如果您想在std::any
个实例的向量中找到一个std::any
实例,答案是否定的。
std::any
确实需要一些“魔术”才能处理未知对象类型的创建,但是这种机制是私有的,必须仅支持对象创建而不是相等比较。
可以使用相同的方法来实现您要寻找的内容,但是不能使用未发布所需详细信息的标准std::any
来实现。 “管理器”模板需要枚举所有可能的操作,例如,在g ++实现中,它们是“访问”,“ get_type_info”,“克隆”,“销毁”,“ xfer”。
variant
完全不同,因为显式列出了所有允许的类型,因此在任何使用它的地方都可以访问所有方法。
答案 2 :(得分:1)
为此目的使用any
并不是any
的良好用法。最好的方法就是使用variant
-因为您有一组封闭的类型:
struct Equals {
template <typename T>
constexpr bool operator()(T const& a, T const& b) const { return a == b; }
template <typename T, typename U>
constexpr bool operator()(T const& a, U const& b) const { return false; }
};
using V = std::variant<int, float, std::string>
bool isItemPresentInAnyVector(std::vector<V> const& items, V const& item)
{
auto it = std::find_if(items.begin(), items.end(), [&](V const& elem){
return std::visit(Equals{}, elem, item);
});
return it != items.end();
}
实际上,它甚至更好,因为正如Kilian指出的那样,variant
的{{3}}已经完全像这样工作了:
using V = std::variant<int, float, std::string>
bool isItemPresentInAnyVector(std::vector<V> const& items, V const& item)
{
return std::find(items.begin(), items.end(), item) != items.end();
}
答案 3 :(得分:0)
如果类型为add_epi32
,int
和float
(或一组有限的类型),则可以使用string
和std::variant
的组合以简单的方式实现您想做的事情:
std::get_if
用于确定存储在std::get_if
中的类型。
一个最小的例子:
std::variant
答案 4 :(得分:0)
应避免与 typeId()
进行比较,因为它依赖于翻译单元。
使用 any_cast
的指针可以使用更安全的方法:
template<typename T>
std::optional<T> find(const std::vector<std::any>& v)
{
for(auto&& e : v){
if(auto ptr = std::any_cast<T>(&e)){
return *ptr;
}
}
return std::nullopt;
}
查找具有给定类型的第一个元素,如果未找到,则查找 nullopt
。
如果我们想找到所有具有特定元素的元素:
template<typename T>
std::vector<T> findAll(const std::vector<std::any>& v)
{
std::vector<T> out;
for(auto&& e : v){
if(auto ptr = std::any_cast<T>(&e)){
out.push_back(*ptr);
}
}
return out;
}
用法:
int main()
{
std::vector<std::any> temp;
temp.emplace_back(std::string("A"));
temp.emplace_back(10);
temp.emplace_back(3.14f);
temp.emplace_back(12);
temp.emplace_back(std::string("B"));
auto outInt = findAll<int>(temp);
std::cout << "out int: " << outInt.size() << std::endl;
for(auto&& out : outInt)
std::cout << out << std::endl;
auto outString = findAll<std::string>(temp);
std::cout << "out string: " << outString.size() << std::endl;
for(auto&& out : outString)
std::cout << out << std::endl;
auto singleInt = find<int>(temp);
if(singleInt)
std::cout << "first int " << *singleInt << std::endl;
auto singleBool = find<bool>(temp);
if(!singleBool)
std::cout << "ok: bool not found" << std::endl;
}