推断成员函数的返回类型

Kor*_*ose 5 c++ templates result-of decltype

在模板函数我试图创建一个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);
Run Code Online (Sandbox Code Playgroud)

现在函数func需要检索的成员函数的返回类型member_funcWidget。请注意,Widget也可以是不同的类型,只要它具有成员函数member_func

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;
}
Run Code Online (Sandbox Code Playgroud)

我尝试了各种方法,例如std::result_of,std::invoke_resultdecltype,但我似乎无法让它工作。这甚至是可能的,如果是,如何实现?

Ric*_*ges 4

这接近你想要的吗?

#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);
}
Run Code Online (Sandbox Code Playgroud)

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

解释:

std::declval<typename Vec::value_type>()生成对 unique_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;
}
Run Code Online (Sandbox Code Playgroud)

这可能更具表现力和通用性(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<>> {});
}
Run Code Online (Sandbox Code Playgroud)

笔记

此代码假定 的 return_typeFoo::member_func不是引用类型。

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

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

b) 使用 将引用类型转换为基本类型std::decay,这将导致创建副本。