【问题标题】:Returning arbitrary types from a function从函数返回任意类型
【发布时间】:2013-04-19 11:54:58
【问题描述】:

我想从函数返回任意类型。返回类型动态地取决于多态函数调用。例如,以下从具有不同列数的 CSV 文件中读取值,

struct File 
{
    virtual SOMETHING getTuple();
};

struct File1 : File
{
    SOMETHING getTuple()
    {   
        return std::tuple<int, double, string>();
    }    
};

struct File2 : File
{
    SOMETHING getTuple()
    {   
        return std::tuple<string, string>();
    }    
};

int main() 
{
    std::ifstream fs("file.csv");
      File2 f;
    BOOST_AUTO(tuple, f.getTuple())
    BOOST_AUTO(row, read(fs,tuple));
    BOOST_FOREACH(BOOST_TYPEOF(tuple) element , row )
    {
        for_each(element,print());
        std::cout << std::endl;
    }
};    

如何编写getTuple() 签名以根据调用的对象返回不同的类型?

解决方案:

class File1
{
    std::ifstream ifs;
public:
    typedef boost::fusion::vector<int, double, std::string> tuple; 
    File1() : ifs("file1.csv") {}

    std::ifstream& getfs()
    {
        return ifs;
    }
};

class File2
{
    std::ifstream ifs;
public:
    typedef boost::fusion::vector<std::string, std::string> tuple; 
    File2() : ifs("file2.csv") {}

    std::ifstream& getfs()
    {
        return ifs;
    }
};

int main()
{
    File2 f;
    typedef File2::tuple tuple;

    BOOST_AUTO(x, read(f.getfs(),tuple()));
    BOOST_FOREACH(tuple e , x )
    {
        for_each(e,print());
        std::cout << std::endl;
    }
}

【问题讨论】:

    标签: c++ templates boost boost-fusion boost-mpi


    【解决方案1】:

    你无法做到这一点。函数签名需要在编译时确定,因此它不能依赖于对象的动态类型。

    您可以做的最接近的方法是使用CRTP 进行静态多态性。也就是说,执行以下操作:

    template<class Derived>
    struct FileBase 
    {
        typename Derived::TupleType getTuple()
        {
            return typename Derived::TupleType();
        }
    };
    
    
    struct File1 : FileBase<File1>
    {
       typedef std::tuple<int, double, string> TupleType;
    };
    
    struct File2 : FileBase<File2>
    {
        typedef std::tuple<string, string>() TupleType; 
    };
    

    这将提供您在给定示例中想要的行为,但它不会通过运行时多态来工作。

    【讨论】:

    • 感谢 CRTP 提示。不幸的是,它忽略了这样一个事实,即使用 CRTP 基类模板成员函数的主体仅在编译器知道整个派生类声明之后才实例化,因此在编译 FileBase 时,TupleType 是未知的。请参阅我上面不使用 CRTP 的解决方案。看起来合理吗?
    • @user1626720 很抱歉,在撰写本文时我无法尝试代码,因此出现问题并不奇怪。假设您无法使用 C++11(auto 关键字和 tuple 将使您的代码更简单),您的解决方案似乎是合理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    相关资源
    最近更新 更多