c++ - 如何使用 static_assert 检查函数签名是否正确

标签 c++ static-assert compile-time-type-checking

代码

我有一个遵循 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); });
    }

问题

但是现在没有对主题和观察者之间的类型匹配进行任何编译时检查。 (编辑有人指出,不能保证 Observer<T> 实际上在其 T 函数签名中使用 OnEvent)

我想向函数添加静态强制转换,以检查两种类型 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 函数不能是 模板,它无法返回除 void 之外的任何内容,因此需要被标记为 const,并且它必须采用 const T&,即使 Tint

关于c++ - 如何使用 static_assert 检查函数签名是否正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63612944/

相关文章:

c++ - 我如何从 C++ 文件中找到一个字符串并使用以下字符串删除它?

c++ - 通过 decltype 表达式调用时 static_assert 是否应该工作?

c++ - 使用 static_assert 检查传递给宏的类型

c++:创建一个可以调用任何函数的计时器/警报类?

c++ - 单向链表 C++ ostream 和 istream -- 输出内存地址

c++ - 传入数据包版本处理 - 设计问题

c++ - 订购标准库容器类型的 static_assert() 的优雅方式?

flutter - 为什么dart不会抛出编译时错误类型异常。运行时间?

c++ - 在编译时检测 T 是否是引用成员