使用 C++20 概念清理静态接口

问题描述

我试图使用 C++20 概念创建一个静态接口,以下代码似乎可以完成这项工作:

template <class FOO>
concept FooConcept = requires {
    static_cast<void (FOO::*)(int)>(&FOO::operator());
    static_cast<void (FOO::*)(char)>(&FOO::operator());
};

特别地,如果类 FooConcept 重载 FOO 两次:分别带有一个 operator() 参数和一个 int 参数,则 char 被类 template <class FOO> concept FooConcept = requires (FOO foo,int i,char c) { { foo(i) } -> std::same_as<void>; { foo(c) } -> std::same_as<void>; }; 满足.

这个解决方案似乎工作正常,但它看起来并不漂亮。事实上,我更喜欢以下形式:

template <class FOO>
concept FooConcept = std::invocable<FOO,int> && std::invocable<FOO,char>;

main

但是,由于隐式转换,这些方法不起作用(请参阅 this post)。 是否有更好、更“语义”的方式来表达这种约束?

解决方法

借助一些帮助程序和非final 类,您可能会这样做:

template <typename T>
struct DeletedOperator : T
{
    using T::operator ();

    template <typename ... Ts>
    void operator()(Ts&&...) = delete;

    template <typename ... Ts>
    void operator()(Ts&&...) const = delete;
};

template <class FOO>
concept FooConcept = requires (DeletedOperator<FOO> foo,int i,char c) {
    { foo(i) } -> std::same_as<void>;
    { foo(c) } -> std::same_as<void>;
};

Demo

我认为我们可以通过调整辅助函数来摆脱非final约束。