【问题标题】:Deduce return type of member function推断成员函数的返回类型
【发布时间】:2018-06-06 09:00:57
【问题描述】:

在模板函数中,我试图创建一个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需要获取Widget的成员函数member_func的返回类型。注意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;
}

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

【问题讨论】:

  • 您只能在该类的实例上调用成员函数,而不能在类类型上调用成员函数(...::element_type 就是这样)。答案中使用的std::declval 是在未评估(例如decltype)上下文中获取类型实例的惯用方式。

标签: c++ templates decltype result-of


【解决方案1】:

这接近你想要的吗?

#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&lt;typename Vec::value_type&gt;() 生成对 unique_ptr 的引用(必须在未评估的上下文中使用)。然后我们采取调用generated_reference-&gt;member_function()的decltype。

这与vec[0]-&gt;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 的return_type 不是引用类型。

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

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

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

【讨论】:

  • 它可能对decay_t ret_type 有用,因为 std::vector 不喜欢 const 和类型中的引用。
  • @Jarod42 添加注释
  • 好的,现在我明白了。我喜欢更通用的方法,并以using ret_type = std::decay_t&lt;decltype((*std::begin(vec))-&gt;member_func())&gt;; 解决。谢谢!
  • @KorbenDose 我同意,我认为这是最具表现力的。很高兴能帮上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多