代码之家  ›  专栏  ›  技术社区  ›  KorbenDose

推导成员函数的返回类型

  •  3
  • KorbenDose  · 技术社区  · 6 年前

    在模板函数中,我试图创建 std::vector 用它 value_type 依赖于函数的模板参数的成员函数。此模板参数仅限于包含具有特定函数的特定类型的唯一指针的向量。例如:

    /* somewhere in the code */
    std::vector< std::unique_ptr< Widget > > myVec;
    /* work with myVec and fill it, then call the relevant function */
    func(myVec);
    

    现在函数 func 需要检索成员函数的返回类型 member_func 属于 Widget . 注意 小装置 也可以是其他类型,只要它具有成员函数 成员函数 .

    template <typename Vec>
    void func(const Vec& vec) {
      using ret_type = decltype(Vec::value_type::element_type::member_func()); // Doesn't work
      std::vector< ret_type > local_vec;
    }
    

    我试过很多种方法,例如。 std::result_of , std::invoke_result decltype ,但我似乎做不到。这是可能的吗?如果是的话,怎么可能实现呢?

    1 回复  |  直到 6 年前
        1
  •  4
  •   Richard Hodges    6 年前

    这接近你想要的吗?

    #include <vector>
    #include <utility>
    #include <memory>
    
    struct Foo
    {
        int member_func();
    };
    
    template <typename Vec>
    void func(const Vec& vec) {
    
        using ret_type = decltype(std::declval<typename Vec::value_type>()->member_func());
    
        std::vector< ret_type > local_vec;
    }
    
    
    int main()
    {
        std::vector<std::unique_ptr<Foo>> v;
        func(v);
    }
    

    演示: https://godbolt.org/g/dJkSf1

    说明:

    std::declval<typename Vec::value_type>() 生成对唯一ptr的引用(必须在未评估的上下文中使用)。然后我们采用调用的decltype generated_reference->member_function() .

    这与 vec[0]->member_func()

    实际上,我们可以这样写:

    template <typename Vec>
    void func(const Vec& vec) {
    
        using ret_type = decltype(vec.at(0)->member_func());
    
        std::vector< ret_type > local_vec;
    }
    

    可能更具表现力和通用性( Vec 现在可以是任何类似于向量的类型,并将类似于指针的东西保存到 Foo )

    而且,我们越是泛化地接近推论,我们的 func 功能变成:

    #include <vector>
    #include <utility>
    #include <memory>
    #include <set>
    #include <iterator>
    
    struct Foo
    {
        int member_func();
    };
    
    template <typename Vec>
    void func(const Vec& vec) {
    
        using ret_type = decltype((*std::begin(vec))->member_func());
    
        std::vector< ret_type > local_vec;
    }
    
    
    int main()
    {
        std::vector<std::unique_ptr<Foo>> v;
        func(v);
        func(std::array<std::unique_ptr<Foo>, 10> { });
    
        Foo* foos[] = { nullptr, nullptr };
        func(foos);
    
        func(std::set<std::shared_ptr<Foo>, std::owner_less<>> {});
    }
    

    注释

    此代码假定返回类型为 Foo::member_func 不是引用类型。

    如果有可能,我们需要决定是否使用元编程来:

    a)将引用类型转换为STD::RealthyTyWrpector,以便它们可以存储在向量中,或者

    b)使用 std::decay ,这将导致复制。