【问题标题】:How to static_assert to check function signature is correct如何通过 static_assert 检查函数签名是否正确
【发布时间】:2020-08-27 09:20:14
【问题描述】:

代码

我有一个遵循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&lt;T&gt;在其OnEvent函数签名中实际使用T

我想向检查Subject&lt;**T**&gt;Observer::OnEvent(const **T**&amp;) 两种类型是否相同的函数添加一个静态转换,以防止自动类型转换。如下所示。

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 说明符指的是 'Observer' 中的非类型成员 'OnEvent'

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

我尝试过的


【问题讨论】:

  • 是的,但是第一个如何确保OnEvent 有一个与T 匹配的参数,只有当模板类使用其模板作为OnEvent 的参数时才会出现这种情况。
  • 是的,我只是想确保我理解正确,问题在第一个示例中也仍然存在。
  • 你已经要求Observer有一个函数OnEvent(OtherT value)。为什么不要求一个类型名:using EventArg = OtherT,然后使用static_assert&lt;std::is_same_v&lt;T, typename Observer::EventArg &gt; &gt;
  • 关键是如果你需要template&lt;typename T&gt; struct Observer { void OnEvent(T e) {}};,那么你也可以需要struct Observer {using EventArg = SomeType; void OnEvent(EventArg e) {}],你可以检查Observer::EventArg,它和你的第一个例子一样可靠。但肯定不是您要求的可靠性。这个using EventArg = SomeType; 存在于std 库中的许多地方(以及其他地方),用于获取有关某些类型的类的信息(例如value_type', allocator_type, size_type, … in std::vector`)。
  • @Troyseph 在这种特殊情况下可能不是问题。我现在无法举出一个例子,但在某些情况下,您可能想要获取参数的实际类型或类的其他类型。并且定义一个类必须有一个清晰的接口,提供一个或多个using sometype_t = its_actual_type; 并相应地使用它们,这使得许多事情变得更容易和一致。

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


【解决方案1】:

我不清楚你在这里想要什么限制。 最严格的做法是强制执行以下内容:

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

如果OnEvent 函数不能是template,它不能返回除void 之外的任何东西,它需要标记为const,它必须采用const T&amp; , 即使Tint

【讨论】:

  • 啊,我只是在调查decltype!会试试这个
  • 我的最终代码使用static_assert(std::is_same_v&lt;decltype(&amp;Observer::OnEvent), void (Observer::*)(const T&amp;...) const&gt;);,唯一的区别是我的真实世界代码有一个可变参数Subject 模板。非常好的答案,谢谢,比我正在调查的所有 SFINAE 选项都简单得多,这需要制作多个额外的模板类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-04
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 2022-08-17
相关资源
最近更新 更多