约束 class 模板函数以接受特定的 POD 类型

Constraining class template function to accept a specific POD type

我正在自学 C++20 的新概念功能,但在尝试确保必须存在的成员函数只接受特定类型时遇到了障碍。我发现 向我展示了如何确保任何功能都可以存在。然后我想通过确保存在具有特定参数的函数来更进一步。我首先定义 T 类型必须有一个 number() 函数 returns 一个 int

#include <concepts>

template <typename T>
concept MyRequirement = requires (T t) 
{
    { t.number(int) } -> std::same_as<int>;
};

template <typename T>
  requires MyRequirement<T>
struct RequiresBool
{
  T t;
};

struct GoodType
{
    int number(int x) { return x; };
};

int main() 
{
    RequiresBool<GoodType> good_object;
}

但是 gcc 给了我以下错误:

<source>:7:16: error: expected primary-expression before 'int'
    7 |     { t.number(int) } -> std::same_as<int>;
      |                ^~~"

所以我将其更改为以下有效。

template <typename T>
concept MyRequirement = requires (T t, int x) 
{
    { t.number(x) } -> std::same_as<int>;
};

然而,当我将 GoodType 中的函数签名更改为 int number(double x) 时,它仍然有效。当然,double 可以隐式转换为 int,这也适用于普通函数。我可以通过在 GoodType 中声明(但不定义)int number(double); 来解决这个问题,这会在编译期间给我一个错误,但这让编写模板 class 的人有责任记住这样做。

这适用于其他类型,例如

template <typename T>
concept MyRequirement = requires (T t, std::string x)
{
    { t.number(x) } -> std::same_as<int>; //int number(int x) is now invalid
};

但是integers/doubles让我很头疼。

是否有某种方法确保 MyRequirement 中 x 的类型必须是使用 C++20 概念的整数?

我还不熟悉概念,所以可能有更惯用的方法。但这对我来说很直观并且有效。

#include <type_traits>

template <typename T>
concept MyRequirement = std::is_same_v<decltype(&T::number), int (T::*)(int)>;

这包括 return 类型和参数。

如果不熟悉,int (T::*)(int) 是一个指向成员函数的指针,其签名 int(int) 属于 class T.
decltype(&T::number) 获取指向 T 成员 number 的指针的类型。

复合要求 ({ expression}) 检查表达式是否格式正确,因此会发生隐式类型转换。 int 可以隐式转换为 double,但 std::string 不能隐式转换为 int.

您可以在复合要求中使用指向成员的指针:

template <typename T>
concept MyRequirement = requires {
    { &T::number } -> std::same_as<int (T::*)(int)>;
};