gpt4 book ai didi

c++ - 什么是 "right"类型删除成员函数指针的方法?

转载 作者:行者123 更新时间:2023-12-01 14:07:05 24 4
gpt4 key购买 nike

我正在编写一个测试装置,它涉及确保在适当的时间调用某些回调(实际上是 Qt 信号,但就我的问题而言,这无关紧要)。为了解决这个问题,我创建了一个辅助类,用于记录回调(信号)何时触发到列表中。

这个列表需要能够记录哪个回调(信号)被触发。我也希望不需要专门为此目的创建新的枚举。我的想法是将信号的地址记录为类型删除的指针,以便我可以根据信号的地址检查记录。

为了让自己更轻松一些,我将信号类型记录为:

template <typename Object>
class SignalType
{
public:
SignalType() = default;
SignalType(SignalType const&) = default;
SignalType(SignalType&&) = default;

template <typename R, typename... Args>
SignalType(R (Object::*member)(Args...))
: member{reinterpret_cast<void (Object::*)()>(member)} {}

template <typename R, typename... Args>
bool operator==(R (Object::*other)(Args...)) const
{ return this->member == reinterpret_cast<void (Object::*)()>(other); }

private:
void (Object::*member)() = nullptr;
};

这从使用的角度“隐藏”了类型删除,所以我以后可以写:

QCOMPARE(event.type, &SomeObject::someMethod);

......无需用 Actor 阵容困惑。

然而,GCC 不高兴:
warning: cast between incompatible pointer to member types from ‘void (SomeObject::*)(...)’ to ‘void (SomeObject::*)()’ [-Wcast-function-type]

有没有办法让 GCC 开心而不求助于诊断 #pragma s 只是关闭警告?是否有其他一些“更好”的方法来实现这种特殊的类型删除? (请注意,我不需要调用 SignalType 封装的成员;我只需要能够测试是否相等。)

叹。应该搜索警告消息,而不是我想要做的。从技术上讲,我猜这是 Cast Between Incompatible Function Types in gcc 的拷贝,但是这只询问如何摆脱警告,并不清楚代码试图完成什么。因此,为了我可以在这里学到一些有用的东西,请关注是否有其他一些“更干净”的方法来实现我的目标,而不是仅仅将其关闭为重复项并说“它无法修复”。

最佳答案

这是一个保存函数指针的解决方案,该函数指针可以比较相同类型的两个值,同时还充当 std::type_info在运行时检查两种类型是否相同。它将函数指针存储在 char[] 中.

#include <new>

template<typename Object>
class SignalType
{
public:
SignalType() = default;
SignalType(SignalType const&) = default;
SignalType& operator=(SignalType const&) = default;

template<typename R, typename... Args>
SignalType(R (Object::*member)(Args...)) noexcept
: comparator(&compare_members_from_void_ptr<R, Args...>) {
using member_ptr_type = R(Object::*)(Args...);
static_assert(sizeof(member_ptr_type) <= sizeof(void(Object::*)()), "Member pointer type too large?");
static_assert(alignof(member_ptr_type) <= alignof(void(Object::*)()), "Member pointer align too large?");
// Don't need to destruct since it has a trivial destructor
new (member_storage) member_ptr_type(member);
}

bool operator==(const SignalType& other) const {
if (!comparator) return !other.comparator; // Check both empty
// Same comparator implies same type
return comparator == other.comparator && comparator(member_storage, other.member_storage);
}
bool operator!=(const SignalType& other) const {
return !(*this == other);
}

// Return true if these contain pointers to members of the same type
bool is_same_type_as(const SignalType& other) const {
return comparator == other.comparator;
}

// true if holding a typed pointer (could still be nullptr)
explicit operator bool() const {
return comparator;
}

// Check if holding an `R(Object::*)(Args...)`
template<typename R, typename... Args>
bool is_type() const noexcept {
return comparator && comparator == &compare_members_from_void_ptr<R, Args...>;
}

// Returns the held function pointer if it is of type R(Object::*)(Args...), else nullptr
template<typename R, typename... Args>
R(Object::* get() const noexcept)(Args...) {
return is_type<R, Args...>() ? *static_cast<R(Object::**)(Args...)>(static_cast<void*>(member_storage)) : nullptr;
}
private:
alignas(void(Object::*)()) char member_storage[sizeof(void(Object::*)())];
bool (*comparator)(const void*, const void*) = nullptr;

template<typename R, typename... Args>
static bool compare_members_from_void_ptr(const void* a, const void* b) noexcept {
return *static_cast<R(Object::*const *)(Args...)>(a) == *static_cast<R(Object::*const *)(Args...)>(b);
}
};

关于c++ - 什么是 "right"类型删除成员函数指针的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61758320/

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