如何static_assert检查函数签名是否正确

How to static_assert to check function signature is correct

代码

我有一个遵循 Observer Pattern.

的模板类型
template <typename T>
class Subject {
public:
    template <template<typename> typename Observer>
    void AddObserver(Observer<T>& observer)
    {
        observers.push_back([&](const T& value) { observer.OnEvent(value); });
    }

    void Event(const T& value) const
    {
        for (auto& o : observers) { 
            o.OnEvent(value) 
        }
    }

private:
    std::vector<std::function<void(const T&)>> observers;
};

上面的效果很好,但前提是 Observer 是模板化类型。所以我可以修改模板签名并接受任何类型,不管它们是否被模板化。

    template <typename Observer>
    void AddObserver(Observer& observer)
    {
        observers.push_back([&](const T& value) { observer.OnEvent(value); });
    }

问题

但是现在没有任何编译时检查 Subject 和 Observer 之间的类型匹配。 (EDIT 已经指出不能保证 Observer<T> 在其 OnEvent 函数签名中实际使用 T

我想向函数添加一个静态转换,以检查 Subject<**T**>Observer::OnEvent(const **T**&) 两种类型是否相同,以防止自动类型转换。类似下面的内容。

static_cast(std::is_same<T, **type_of_first_param**(Observer::OnEvent)>::value, "Subject/Observer type mistatch.");

我需要帮助的可能方法

如果我无法从函数签名中提取类型,也许我可以构造一个函数签名来与之进行比较?

static_cast(std::is_same<**Observer::MadeUpFunc(const T&)**, Observer::OnEvent>::value, "Subject/Observer type mistatch.");

我正在调查 this QA,我很确定它包含我需要的答案,只是需要一些时间和指导来找出答案。

我试过以下方法,但出现编译时错误

typename specifier refers to non-type member 'OnEvent' in 'Observer'

static_assert(std::is_same<typename Observer::OnEvent, void (Observer::*)(const T&...)>::value, "");

我试过的


我不清楚你想要什么限制。 最具限制性的是强制执行如下内容:

static_assert(std::is_same_v<decltype(&Observer::OnEvent),
                             void (Observer::*)(const T&) const>);

其中 OnEvent 函数不能是 template,它不能 return 除了 void 之外的任何东西,它需要被标记为 const,并且必须使用 const T&,即使 Tint