c++ - 我可以编写一个需要函数模板的 C++ 概念吗?必须向该函数模板提供一些枚举值作为模板参数?

标签 c++ enums c++20 c++-concepts

我想编写一个 C++ 概念来描述具有由枚举值专门化的函数模板的类型。例如,

enum class categories { 
  t1, 
  t2 
};

struct notifiable_type {
  template<categories category>
  auto notification() {}
};

auto main() -> int {
  notifiable_type().notification<categories::t1>();
}

到目前为止,我已经尝试过:

// 1
template<typename notifiable_t, typename notification_t>
concept notifiable = std::is_enum<notification_t>::value && requires(notifiable_t t, const notification_t n) {
  { t.template notification<n>() } -> std::same_as<void>;
};

// 2
template<typename notifiable_t, typename notification_t>
concept notifiable = std::is_enum<notification_t>::value && requires(notifiable_t t) {
  { t.template notification<std::declval<notification_t>()>() } -> std::same_as<void>;
};

但是,这些似乎都没有按照预期的方式工作:

  1. 第一个案例有错误Constraint variable 'n' cannot be used in an evaluated context .
  2. 第二种情况编译没有任何错误,但是 notifiable<notifiable_type, categories>不满意。

有人可以帮我澄清一下吗?我想写的可能吗?

最佳答案

你与这个非常接近(我继续将 std::is_enum<E>::value 更改为 std::is_enum_v<E> ,并且还减少了类型的名称,因为它们很长并且几乎彼此相同,这让我感到困惑位):

template<typename T, typename E>
concept notifiable =
    std::is_enum_v<E>
    && requires(T t, const E n) {
        { t.template notification<n>() } -> std::same_as<void>;
    };

问题是你不能使用n就像那样,因为它需要是一个常数,但事实并非如此。因此,解决方案是不要发明 E 类型的变量而是发明 E 类型的 。而且,好吧,0与任何值一样好:

template <typename T, typename E>
concept notifiable = std::is_enum_v<E>
    && requires(T t) {
        { t.template notification<E{}>() } -> std::same_as<void>;
    };

E是一个枚举,我们知道E{}已验证。不需要declval ,这同样与您原来的方法存在相同的问题:它不是一个常量,但它需要是一个常量。

一个类似的解决方案,尽管更冗长且通常更奇怪,是:

template <typename T, typename E>
concept notifiable = std::is_enum_v<E>
    && requires(T t, std::integral_constant<E, E{}> n) {
        { t.template notification<n>() } -> std::same_as<void>;
    };

现在,这个有效,因为 integral_constant<T, V> constexpr 可转换为 T值(value)V 。这种转换在很多情况下都非常有用,因为它允许以保留常数的方式近似地将常量作为函数参数传递。

但在这种情况下这是没有意义的,所以我只是为了说明而展示它。


请注意,这仍然是有限的,我们只是专门检查 E{0}有效 - 不是任何E有效(我们通常不能这样做)。这可能已经足够好了,尽管如果您遇到 T::notification 的情况,您可能会得到假阴性结果。对其 E 有额外的限制.

关于c++ - 我可以编写一个需要函数模板的 C++ 概念吗?必须向该函数模板提供一些枚举值作为模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75818173/

相关文章:

c++ - "libgcc_s_sjlj-1.dll"丢失

来自 std::cout 的 C++11 std::shared_ptr<std::ostream>

c++ - 使用来自 streambuf 的 boost::asio::ip::tcp 将数据部分写入 TCP 套接字

c++ - 无法访问嵌套私有(private)枚举的枚举数

c - 定义C中用于存储的枚举的数据类型

c++ - 如何将模板化固定字符串传递给另一个类的构造函数的重载

c++ - 无法理解堆栈实现的 isEmpty 函数中的返回语句

java - 如何在其 toString() 函数的重写中修改枚举的字符串表示形式?

c++ - Boost.ASIO 如何将链与 c++20 协程一起使用

c++ - 闰秒和 std::chrono