C++概念可以检查一个类型是否与另一个概念的任何类型兼容吗?

vuktfyat  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(115)

我想创建一个概念Handler,它将检查实现者是否能够接受任何满足Update概念的类型, -而实际上不必用我拥有的每一个可能的update对象示例化这个概念。

template <typename T>
concept Update = requires (T update) {
  { update.get_value(); } -> std::same_as<std::string>;
  ...
};

template <typename T>
concept Handler = requires (T handler, Update update) {
  handler.on_update(update);
};

然而,除非我给Handler概念添加一个额外的参数,并传递Update概念的一个特定示例,否则这实际上并不起作用。有什么方法可以实现我所尝试的吗?我曾考虑过创建一个模拟FakeUpdate对象来实现Update概念(这正是我希望编译器所做的),但感觉有点难看。

u7up0aaq

u7up0aaq1#

下面的例子展示了一个实现你想要的东西的方法。我们简单地定义了UpdateableDummy结构体,并把它传递给我们的Handleable概念。如果Handleable概念可以从Handleable类的模板中推导出传递给on_update的类型,那就太好了。但对于 * 确实 * 是Handleable但不是模板的类,这将失败(参见non_templateHandleableExample)。因此,也许在未来的语言标准中,Handleable概念中对on_update的调用类型,可以从针对Handleablelity检查的类中推导出来
还应注意,HandleableExample声明中的template <Updateable T>要求TUpdateable

// Example program
#include <iostream>
#include <string>
#include <concepts>

template <typename T>
concept Updateable = requires (T update) {
  { update.get_value() } -> std::same_as<std::string>;
};

// Updateable Dummy Type
struct UpdateableDummy {
    std::string get_value(void) {
        return "dummyValue";
    }
};

template <typename U, typename V>
concept Handleable = requires (U handler, V updateableInstance) {
    handler.on_update(updateableInstance);
};

// Updateable Example Type
struct UpdateableExample {
    std::string get_value(void) {
        return "exampleValue";
    }
};

// Not Updateable Example Type
struct NotUpdateableExample {
    void print_value(void) {
        std::cout << "dummyValue\n";
    }
};

// Handleable Example Type
template <Updateable T>
struct HandleableExample {
    void on_update(T t) {
        t.get_value();
    }
};

// Not Handleable Example Type
template <Updateable T>
struct NotHandleableExample {
    void when_update(T t) {
        t.get_value();
    }
};

// Handleable Struct that doesn't use templates
struct non_templateHandleableExample {
    void on_update(UpdateableExample updateableInstance) {
        updateableInstance.get_value();
    }
};

// Works With Both UpdateableDummy and UpdateableExample Type
static_assert(Handleable<HandleableExample<UpdateableDummy>,UpdateableDummy>);
static_assert(Handleable<HandleableExample<UpdateableExample>,UpdateableExample>);

// Works with non_templateHandleableExample
static_assert(Handleable<non_templateHandleableExample,UpdateableExample>);

// Fails For not updateable inner-type
static_assert(Handleable<HandleableExample<NotUpdateableExample>,NotUpdateableExample>);

// Fails For not handleable outer-type
static_assert(Handleable<NotHandleableExample<UpdateableDummy>,UpdateableDummy>);

// Fails For not handleable outer-type AND not updateable inner-type
static_assert(Handleable<NotHandleableExample<NotUpdateableExample>,NotUpdateableExample>);

int main()
{
  // Comment out intentionally failing static assertions to test the auto type keyword example
  Handleable<UpdateableExample> auto handleableInstance = HandleableExample<UpdateableExample>();
}

相关问题