gpt4 book ai didi

c++ - 匹配继承的成员函数的类型

转载 作者:IT老高 更新时间:2023-10-28 22:59:58 25 4
gpt4 key购买 nike

我有以下代码片段,但无法编译。

#include <iostream>

struct A {
void foo() {}
};

struct B : public A {
using A::foo;
};

template<typename U, U> struct helper{};

int main() {
helper<void (A::*)(), &A::foo> compiles;
helper<void (B::*)(), &B::foo> does_not_compile;

return 0;
}

它从 &B::foo 开始无法编译解析为 &A::foo ,因此它不能匹配建议的类型 void (B::*)() .由于这是我用来检查非常具体的接口(interface)的 SFINAE 模板的一部分(我正在强制使用特定的参数类型和输出类型),我希望它能够独立于继承工作,同时保持检查的可读性。

我尝试的包括:

  • 类型转换论点的第二部分:

    helper<void (B::*)(), (void (B::*)())&B::foo> does_not_compile;

    不幸的是,这没有帮助,因为第二部分现在不被识别为常量表达式,并且失败了。

  • 我已经尝试将引用分配给一个变量,以便检查。

    constexpr void (B::* p)() = &B::foo;
    helper<void (B::* const)(), p> half_compiles;

    这个代码被clang 3.4接受了,但是g++ 4.8.1拒绝了,不知道谁说的对。

有什么想法吗?

编辑:由于许多评论都要求提供更具体的问题版本,我将在此处写下:

我正在寻找的是一种明确检查类是否尊重特定接口(interface)的方法。此检查将用于验证模板化函数中的输入参数,以便它们尊重这些函数所需的契约(Contract),以便在类和函数不兼容的情况下提前停止编译(即类型特征类型的检查)。

因此,我需要能够验证我请求的每个成员函数的返回类型、参数类型和数量、常量等。最初的问题是我用来验证匹配的更大模板的检查部分。

最佳答案

发布于 https://ideone.com/mxIVw3 的问题的有效解决方案下面给出 - 另见 live example .

这个问题在某种意义上是Deduce parent class of inherited method in C++ 的后续问题。 .在 my answer ,我定义了一个类型特征 member_class 从给定的指向成员函数类型的指针中提取一个类。下面我们使用更多的特征来分析然后综合回这样的类型。

首先,member_type 提取签名,例如void (C::*)() 给出 void():

template <typename M> struct member_type_t { };
template <typename M> using member_type = typename member_type_t <M>::type;

template <typename T, typename C>
struct member_type_t <T C::*> { using type = T;};

然后,member_class 提取类,例如void (C::*)() 给出 C:

template<typename>
struct member_class_t;

template<typename M>
using member_class = typename member_class_t <M>::type;

template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...)> { using type = C; };

template<typename R, typename C, typename... A>
struct member_class_t <R(C::*)(A...) const> { using type = C const; };

// ...other qualifier specializations

最后,member_ptr 合成一个指向给定类和签名的成员函数类型的指针,例如C + void() 给出 void (C::*)():

template <typename C, typename S>
struct member_ptr_t;

template <typename C, typename S>
using member_ptr = typename member_ptr_t <C, S>::type;

template <typename C, typename R, typename ...A>
struct member_ptr_t <C, R(A...)> { using type = R (C::*)(A...); };

template <typename C, typename R, typename ...A>
struct member_ptr_t <C const, R(A...)> { using type = R (C::*)(A...) const; };

// ...other qualifier specializations

前面的两个特征需要更多的特化才能使不同的限定词更通用,例如const/volatile 或引用限定符。有 12 种组合(或包括数据成员在内的 13 种);一个完整的实现是here .

这个想法是任何限定符都由 member_class 从指向成员函数的指针类型转移到类本身。然后 member_ptr 将限定符从类传回指针类型。虽然限定符在类类型上,但可以使用标准特征自由操作,例如添加或删除 const、左值/右值引用等

现在,这是您的 is_foo 测试:

template <typename T>
struct is_foo {
private:
template<
typename Z,
typename M = decltype(&Z::foo),
typename C = typename std::decay<member_class<M>>::type,
typename S = member_type<M>
>
using pattern = member_ptr<C const, void()>;

template<typename U, U> struct helper{};

template <typename Z> static auto test(Z z) -> decltype(
helper<pattern<Z>, &Z::foo>(),
// All other requirements follow..
std::true_type()
);

template <typename> static auto test(...) -> std::false_type;

public:
enum { value = std::is_same<decltype(test<T>(std::declval<T>())),std::true_type>::value };
};

给定类型 Z,别名模板 pattern 使用 decltype(&Z::foo 获取成员指针的正确类型 M ),提取其decay的类C和签名S,合成一个新的pointer-to-member-function类型具有类 C const 和签名 void(),即 void (C::*)() const。这正是您所需要的:它与您的原始硬编码模式相同,类型 Z 替换为正确的类 C (可能是基类),如由 decltype 找到。

图形化:

M = void (Z::*)() const  ->   Z         +   void()
-> Z const + void()
-> void (Z::*)() const == M
-> SUCCESS

M = int (Z::*)() const& -> Z const& + int()
-> Z const + void()
-> void (Z::*)() const != M
-> FAILURE

事实上,这里不需要签名S,所以也不需要member_type。但是我在这个过程中使用了它,所以为了完整起见,我把它包括在这里。它可能在更一般的情况下有用。

当然,这一切都不适用于多个重载,因为 decltype 在这种情况下不起作用。

关于c++ - 匹配继承的成员函数的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23499611/

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