计算函数指针的类型
Computing the type of a function pointer
考虑以下内容:
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;
};
第二类参数CCD_ 20是在C++14中模拟CCD_。我们的想法是,我们有下面的偏类型函数。
- 给定一个类型
T
和一个名为element_type
的嵌套typedef
,返回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++
- 如何访问在 c++ 中在类内声明的结构类型指针变量?
- (C )找到基本类型指针的儿童类型
- 表达式必须具有指向对象的指针类型(指针向量)
- 将子项复制构造到父类型指针中
- C 返回类型指针声明
- 调用虚拟函数而不通过类类型指针创建任何对象
- C++ 如何使用类类型指针制作向量
- 为什么基类型指针不能获取派生类对象的地址值?
- 如何在 C++ 中获取映射类型指针,映射
- 如何检查该类型的类型指针是正确对齐的
- 正在转换为短类型指针
- 指向任意类方法的模板非类型指针
- 如何通过强制转换类型指针将字符数组转换为uint16_t
- 指向shared_ptr的不透明类型 C 指针
- C++:从值类型指针强制转换为包含迭代器
- C/C++:访问给定类型指针的位置与访问另一类型指针的相同位置不同
- 比较类型指针
- 数据类型指针使用*(Datatype *)
- 如何打印c++中char类型指针的所有值