C++20 中概念的语法

ATK*_*ATK 2 c++ templates c++-concepts c++20

我们如何将这个问题中的需求转换一个概念

我已尝试以下操作:

template< typename U, typename Tin, typename Tout>
concept MyConditions =
    (
         U::value_type
        &&  Tin::value_type
        &&  Tout::value_type
        && std::is_floating_point_v<typename Tin::value_type>
        && std::is_integral_v<typename U::value_type>
        && std::is_floating_point_v<typename Tout::value_type>
    );
Run Code Online (Sandbox Code Playgroud)

这个概念现在应用于我的成员函数之一:

class test_concept
{
template< typename U, typename Tin, typename Tout>
requires MyConditions <U, Tin, Tout>
static void test_routine(const U&, const Tin&, Tout& );
}
Run Code Online (Sandbox Code Playgroud)

测试时:

std::vector<double> test{ };
std::vector<int> testi{ };
std::vector<double> test2{ };

test_concept::test_routine(testi, test, test2);
Run Code Online (Sandbox Code Playgroud)

使用clang我收到错误消息,指出未找到匹配项,并附有一条注释:

注意:因为替换的约束表达式格式不正确:依赖类型名称 'vector<int, allocator >::value_type' U::value_type 之前缺少 'typename'

Hol*_*Cat 5

您不需要手动检查类型是否存在。如果它们不存在,SFINAEfalse无论如何都会让你的概念默默地返回。所以:

template< typename U, typename Tin, typename Tout>
concept MyConditions =
    std::is_integral_v<typename T::value_type> &&
    std::is_floating_point_v<typename U::value_type> &&
    std::is_floating_point_v<typename Tout::value_type>;
Run Code Online (Sandbox Code Playgroud)

但如果您想显式检查类型,语法如下:

template< typename U, typename Tin, typename Tout>
concept MyConditions =
    requires
    {
        typename U::value_type;
        typename Tin::value_type;
        typename Tout::value_type;
    } &&
    std::is_integral_v<typename T::value_type> &&
    std::is_floating_point_v<typename U::value_type> &&
    std::is_floating_point_v<typename Tout::value_type>;
Run Code Online (Sandbox Code Playgroud)

您还可以将所有条件移至requires

template< typename U, typename Tin, typename Tout>
concept MyConditions =
    requires
    {
        typename U::value_type;
        typename Tin::value_type;
        typename Tout::value_type;
        requires std::is_integral_v<typename T::value_type>;
        requires std::is_floating_point_v<typename U::value_type>;
        requires std::is_floating_point_v<typename Tout::value_type>;
    };
Run Code Online (Sandbox Code Playgroud)

此外,您应该更喜欢标准概念而不是旧特征:

template< typename U, typename Tin, typename Tout>
concept MyConditions =
    requires
    {
        typename U::value_type;
        typename Tin::value_type;
        typename Tout::value_type;
        requires std::integral<typename T::value_type>;
        requires std::floating_point<typename U::value_type>;
        requires std::floating_point<typename Tout::value_type>;
    };
Run Code Online (Sandbox Code Playgroud)

  • @A2LBK 是的,这就是我的意思。我认为这在这里没有什么区别,但在某些情况下确实有区别。请参阅/sf/ask/3644367051/ (2认同)
  • 虽然您可以将所有条件移至“requires”中,但盲目地这样做并不是一个好主意,因为这会将您的概念从公认的原子约束结合变成一个大斑点。从问题中获取概念,这意味着“MyConditions”不再比任何“std::integral/floating_point”部分更具体,因此您不能再重载“MyConditions&lt;T, ...&gt;”函数使用 `std::integral&lt;typename T::value_type&gt;` 函数并让重载解析按您的预期工作。 (2认同)