能够返回不同类型的功能?

use*_*491 9 c++

我试图在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)

备择方案

如果您在编译时知道类型,这是一种方法.如果您在编译时不知道类型但仅在运行时知道类型,那么您有不同的选择:

  1. 使用unions.我只能推荐这个,如果你有非常简单的C-struct类型,在C++标准中称为POD(普通旧数据).
  2. 使用某种类型的变体.例如,boost::variant来自Boost库或QVariantQt库.对于更一般的类型,它们是一种安全的工会.它们还允许在不同类型之间进行一些转换.例如,将某事物设置为整数值将使得可以读取与浮点数相同的值.
  3. 使用boost::any它可以包装任何类型,但不允许它们之间的转换.
  4. 使用继承和多态.对于这种情况,你需要一个共同的基类Base.然后你创建一个指向该基数的指针数组,最好是std::shared_ptrs.所以数组类型是std::vector<std::shared_ptr<Base>>.将std::shared_ptr优于建于指针在这种情况下,因为通过引用计数自动地管理你的记忆.
  5. 使用不关心类型和性能的动态语言.


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


chr*_*ris 6

这完全取决于您想要完成的任务,但是如何做到这一点有多种可能性。以下是一些我想到的:

如果在函数内部决定了特定返回类型列表之一:

由于您编辑了问题,这似乎就是您想要的。你可以尝试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)