【问题标题】:Constraining class template function to accept a specific POD type约束类模板函数以接受特定的 POD 类型
【发布时间】:2019-12-14 23:02:55
【问题描述】:

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

#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); 来解决这个问题,这会在编译期间给我一个错误,但这让编写模板类的人有责任记住这样做。

这适用于其他类型,例如

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
};

但是整数/双精度数让我头疼。

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

【问题讨论】:

    标签: c++ c++20 c++-concepts


    【解决方案1】:

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

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

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

    【讨论】:

    • &T::number中的&是不是必须的,因为它引用了函数对象,需要和返回类型中指定的函数指针进行比较?
    • T::numbercan't be used alone&amp;T::number 是一个指向成员函数的指针,它是少数允许“表示类的非静态数据成员或非静态成员函数的 id 表达式”的上下文之一。
    【解决方案2】:

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

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

    这包括返回类型和参数。

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

    【讨论】:

      猜你喜欢
      • 2020-07-21
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 2018-04-17
      • 2015-11-10
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多