我试图在c ++中创建一个函数,我想知道我是否可以创建它,以便它能够返回不同类型的向量.例如,基于不同的情况,它返回矢量字符串,int,double或......任何东西.在c ++中有可能吗?(我不想使用具有不同arg(S)和不同返回的重载函数)我对C++很新,我的问题可能看起来很愚蠢.
这是我的一段代码:
//零在这里意味着交集
std::vector<??????> findZeros(const mesh::Region& s, char *model) const
{
//Point
if( model == "point" )
{
std::vector<Vertex> zeros;
for(Region::pointIterator it = s.beginPoint(); itv != s.endPoint(); ++itv )
{
if( abs(Val(*it)) < 1.e-12 )
zeros.push_back(*it);
}
std::vector<point> zerosP(zeros.begin(), zeros.end());
return zerosP;
}
//line
else if (EntityS == "line")
{
std::vector<line> zerosE;
std::vector<Point&> PointE;
for(Region::lineIterator ite = s.beginLine(); ite != s.endLine(); ++ite )
{
Line ed = *ite;
Point P0 = ed.point(0);
Point P1 = e.point(1);
if( ......... ) zerosE.push_back(ed);
else if ( ....... )
{
PontE.push_back( P0, P1);
zerosE.push_back(ed);
}
}
Run Code Online (Sandbox Code Playgroud)
//这里我想要返回"点"或"带点的线"或者在上层我们的表面.//我想在一个函数中完成所有操作!}
Ral*_*zky 17
试试这个:
template <typename T>
std::vector<T> func( /* arguments */ )
{
std::vector<T> v;
// ... do some stuff to the vector ...
return v;
}
Run Code Online (Sandbox Code Playgroud)
您可以通过以下方式调用此函数的不同类型:
std::vector<int> func<int>( args );
std::vector<double> func<double>( args );
Run Code Online (Sandbox Code Playgroud)
如果您在编译时知道类型,这是一种方法.如果您在编译时不知道类型但仅在运行时知道类型,那么您有不同的选择:
unions.我只能推荐这个,如果你有非常简单的C-struct类型,在C++标准中称为POD(普通旧数据).boost::variant来自Boost库或QVariantQt库.对于更一般的类型,它们是一种安全的工会.它们还允许在不同类型之间进行一些转换.例如,将某事物设置为整数值将使得可以读取与浮点数相同的值.boost::any它可以包装任何类型,但不允许它们之间的转换.Base.然后你创建一个指向该基数的指针数组,最好是std::shared_ptrs.所以数组类型是std::vector<std::shared_ptr<Base>>.将std::shared_ptr优于建于指针在这种情况下,因为通过引用计数自动地管理你的记忆.fra*_*sco 14
C++17 更新
如果您在编译时知道类型,则可以使用此答案中所示的模板。
如果类型仅在运行时已知,则c++17可以boost::variant使用std::variant.
这是一个工作示例:
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
using variant_vector = std::variant<std::vector<int>, std::vector<std::string>>;
auto get_vector(int i)
{
if (i < 0)
return variant_vector(std::vector<int>(3, 1));
else
return variant_vector(std::vector<std::string>(3, "hello"));
}
int main()
{
auto visit_vec = [](const auto& vec) {
using vec_type = typename std::remove_reference_t<decltype(vec)>::value_type;
if constexpr (std::is_same_v<vec_type, int>)
std::cout << "vector of int:" << std::endl;
else if constexpr (std::is_same_v<vec_type, std::string>)
std::cout << "vector of string:" << std::endl;
for (const auto& x : vec)
std::cout << x << std::endl;
};
std::visit(visit_vec, get_vector(-1));
std::visit(visit_vec, get_vector(1));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在 Coliru 上观看直播。
在上面的代码中,该函数get_vector返回一个包含 a或 astd::variant的对象。使用 检查返回对象的内容。std::vector<int>std::vector<std::string>std::visit
这完全取决于您想要完成的任务,但是如何做到这一点有多种可能性。以下是一些我想到的:
如果在函数内部决定了特定返回类型列表之一:
由于您编辑了问题,这似乎就是您想要的。你可以尝试boost::variant:
boost::variant<int, double, std::string> foo() {
if (something)
//set type to int
else if (something else)
//set type to double
else
//set type to std::string
}
Run Code Online (Sandbox Code Playgroud)
如果返回类型取决于模板参数:
您可以使用 SFINAE 来操纵重载解析:
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
std::vector<int> foo() {...}
template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
std::vector<std::string> foo() {...}
Run Code Online (Sandbox Code Playgroud)
如果返回类型可以是任何类型:
Aboost::any会很好地工作:
boost::any foo() {...}
Run Code Online (Sandbox Code Playgroud)
如果返回类型始终派生自特定类:
返回一个指向基类的智能指针:
std::unique_ptr<Base> foo() {
if (something)
return std::unique_ptr<Base>{new Derived1};
if (something else)
return std::unique_ptr<Base>{new Derived2};
}
Run Code Online (Sandbox Code Playgroud)