c – Deduce返回类型的成员函数

在模板函数中,我试图创建一个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_of,std :: invoke_result和decltype,但我似乎无法使它工作.这是否可能,如果是,它怎么可能实现?

解决方法:

这接近你想要的吗?

#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>()生成对unique_ptr的引用(必须在未评估的上下文中使用).然后我们采用调用generated_reference-> member_function()的decltype.

这与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的return_type不是引用类型.

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

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

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

上一篇:C/C++实战011:解决使用VC++6.0编程遇到的问题


下一篇:c – 当对它们应用decltype时,哪些表达式产生引用类型?