我正在尝试用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);
}
}
//在这里我想要返回“点”或“带点的线”或在我们的表面的上层。 //我想在一个函数中完成所有操作! }
答案 0 :(得分:16)
试试这个:
template <typename T>
std::vector<T> func( /* arguments */ )
{
std::vector<T> v;
// ... do some stuff to the vector ...
return v;
}
您可以通过这种方式调用此函数的不同类型:
std::vector<int> func<int>( args );
std::vector<double> func<double>( args );
如果您在编译时知道类型,这是一种方法。如果您在编译时不知道类型,但仅在运行时知道类型,那么您有不同的选择:
unions
。我只能推荐这个,如果你有非常简单的C-struct类型,在C ++标准中称为POD(普通旧数据)。 boost::variant
或Qt库中有QVariant
。对于更一般的类型,它们是一种安全的工会。它们还允许在不同类型之间进行一些转换。例如,将某事物设置为整数值可以读取与浮点数相同的值。 boost::any
可以包装任何类型,但不允许它们之间的转换。 Base
。然后使用std::shared_ptrs
创建一个指向该基础的指针数组。因此数组类型为std::vector<std::shared_ptr<Base>>
。在这种情况下,std::shared_ptr
比指针内置更好,因为通过引用计数自动管理内存。 答案 1 :(得分:2)
如果您在调用函数之前知道要返回的类型,则可以使用模板。但你不能拥有一个内部决定返回某种类型的函数。
您可以做的是创建一个类,该类将作为返回数据的容器,使用所需数据填充此类的对象,然后返回此对象。
typedef enum { VSTRING, VINT, V_WHATEVER ... } datatype;
class MyReturnClass {
datatype d;
// now either
vector<string> * vs;
vector<int> * vi;
// or
void * vector;
}
MyReturnClass * thisIsTheFunction () {
MyReturnClass * return_me = new MyReturnClass();
return_me->datatype = VSTRING;
return_me->vs = new Vector<String>;
return return_me;
}
答案 2 :(得分:2)
这取决于你想要完成什么,但有多种可能性来实现这一目标。以下是一些想到的内容:
如果在函数内部确定了一个特定的返回类型列表:
由于您编辑了问题,这似乎就是您想要的。您可以尝试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
}
如果返回类型取决于模板参数:
您可以使用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() {...}
如果返回类型可以是任何内容:
boost::any
效果很好:
boost::any foo() {...}
如果返回类型始终来自特定类:
返回指向基类的智能指针:
std::unique_ptr<Base> foo() {
if (something)
return std::unique_ptr<Base>{new Derived1};
if (something else)
return std::unique_ptr<Base>{new Derived2};
}
答案 3 :(得分:2)
C ++ 17更新
如果在编译时知道类型,则可以使用this answer中所示的模板。
如果该类型仅在运行时才知道,并且以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;
}
live on Coliru看到它。
在上面的代码中,函数get_vector
返回一个std::variant
对象,该对象包含一个std::vector<int>
或一个std::vector<std::string>
。使用std::visit
检查返回对象的内容。