gpt4 book ai didi

c++ - 计算函数指针的类型

转载 作者:行者123 更新时间:2023-11-30 03:45:37 24 4
gpt4 key购买 nike

考虑以下几点:

template<typename T>
struct S
{
typedef M< &T::foo > MT;
}

这适用于:

S<Widget> SW;

其中 Widget::foo() 是一些函数

我将如何修改 struct S 的定义以允许以下内容:

S<Widget*> SWP;

最佳答案

你需要的是下面的类型转换。

  • 给出T , 返回 T
  • 给出T * , 返回 T

碰巧标准库已经在 std::remove_pointer 中为我们实现了这个(尽管自己做并不难)。

有了这个,你就可以写

using object_type = std::remove_pointer_t<T>;
using return_type = /* whatever foo returns */;
using MT = M<object_type, return_type, &object_type::foo>;

关于您还想使用智能指针的评论,我们必须重新定义类型转换。

  • 给定一个智能指针类型 smart_ptr<T> , 返回 smart_ptr<T>::element_type , 应该是 T
  • 给定一个指针类型T * , 返回 T
  • 否则,给定T , 返回 T本身

为此,我们必须编写自己的元函数。至少,我不知道标准库中有什么可以帮助解决这个问题。

我们首先定义主要的 template (“否则”情况)。

template <typename T, typename = void>
struct unwrap_obect_type { using type = T; };

默认为 void 的第二个(匿名)类型参数以后会有用。

对于(原始)指针,我们提供以下部分特化。

template <typename T>
struct unwrap_obect_type<T *, void> { using type = T; };

如果我们停在这里,我们基本上会得到 std::remove_pointer .但是我们将为智能指针添加额外的偏特化。当然,我们首先要定义什么是“智能指针”。出于本示例的目的,我们将使用嵌套的 typedef 处理每种类型。名为 element_type作为智能指针。根据需要调整此定义。

template <typename T>
struct unwrap_obect_type
<
T,
std::conditional_t<false, typename T::element_type, void>
>
{
using type = typename T::element_type;
};

第二类参数std::conditional_t<false, typename T::element_type, void>是一种复杂的模拟 std::void_t 的方法在 C++14 中。这个想法是我们有以下部分类型函数。

  • 给定一个类型 T嵌套 typedef名为 element_type , 返回 void
  • 否则,触发替换失败

因此,如果我们处理的是智能指针,我们将获得比主 template 更好的匹配。否则,SFINAE 将不再考虑此部分特化。

这是一个工作示例。 T.C.建议使用 std::mem_fn 调用成员函数。这使代码比我最初的示例更简洁。

#include <cstddef>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <utility>

template <typename ObjT, typename RetT, RetT (ObjT::*Pmf)() const noexcept>
struct M
{
template <typename ThingT>
static RetT
call(ThingT&& thing) noexcept
{
auto wrapper = std::mem_fn(Pmf);
return wrapper(std::forward<ThingT>(thing));
}
};

template <typename T, typename = void>
struct unwrap_obect_type { using type = T; };

template <typename T>
struct unwrap_obect_type<T *, void> { using type = T; };

template <typename T>
struct unwrap_obect_type<T, std::conditional_t<false, typename T::element_type, void>> { using type = typename T::element_type; };

template <typename T>
struct S
{

template <typename ThingT>
void
operator()(ThingT&& thing) const noexcept
{
using object_type = typename unwrap_obect_type<T>::type;
using id_caller_type = M<object_type, int, &object_type::id>;
using name_caller_type = M<object_type, const std::string&, &object_type::name>;
using name_length_caller_type = M<object_type, std::size_t, &object_type::name_length>;
std::cout << "id: " << id_caller_type::call(thing) << "\n";
std::cout << "name: " << name_caller_type::call(thing) << "\n";
std::cout << "name_length: " << name_length_caller_type::call(thing) << "\n";
}

};

class employee final
{

private:

int id_ {};
std::string name_ {};

public:

employee(int id, std::string name) : id_ {id}, name_ {std::move(name)}
{
}

int id() const noexcept { return this->id_; }
const std::string& name() const noexcept { return this->name_; }
std::size_t name_length() const noexcept { return this->name_.length(); }

};

int
main()
{
const auto bob = std::make_shared<employee>(100, "Smart Bob");
const auto s_object = S<employee> {};
const auto s_pointer = S<employee *> {};
const auto s_smart_pointer = S<std::shared_ptr<employee>> {};
s_object(*bob);
std::cout << "\n";
s_pointer(bob.get());
std::cout << "\n";
s_smart_pointer(bob);
}

关于c++ - 计算函数指针的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34690980/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com