【问题标题】:C++ Concepts: How to use 'concept' to check the property of a templated struct?C++ 概念:如何使用“概念”来检查模板结构的属性?
【发布时间】:2020-02-24 13:19:05
【问题描述】:

我目前正在试验新的 c++2a 'concepts' 功能。我下面代码的目标是检查模板结构的某些属性。作为第一个模板参数is 'reserved' for the type to be checked,我很难使用没有requires 表达式或手动指定模板参数的概念。这没什么大不了的,但我喜欢 concept 表示法的清晰性。有没有办法解决这个问题?

编译器

gcc-g++-10.0 (GCC) 10.0.1 20200119 (experimental)
Copyright (C) 2020 Free Software Foundation, Inc.

编译命令

g++-10.0 -std=c++2a file.cc

代码


#include <concepts>

/// Struct has template arguments and a property that can be checked in a concept.
template <bool a> struct A {
  constexpr static bool property() noexcept { return a; }
};

template <typename T, bool a> concept hasProp = std::is_same_v<T, A<a>> && A<a>::property();

template <bool a> requires hasProp<A<a>, a> void works(A<a> c) {} 
template <bool a, hasProp<a> c> void deductionError(c d) {};

// This is a sketch of what I'd like to do:
// template <A<a, b> Class, bool a, bool b> concept hasProp = Class::property;

int main() {
  A<true> a;
  A<false> b;

  works(a);
  //works(b); //doesn't compile as the constraint is not fulfilled, which is desired.

  //deductionError(a); // I get why this deduction error occurs, but is it possible to do this
                      // in a clean way using concepts without having so specify template arguments?
}

【问题讨论】:

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


    【解决方案1】:

    部分类模板特化来拯救:

    template<class T> 
    struct HasProp : std::false_type{};
    
    template<bool a>
    struct HasProp<A<a>> : std::integral_constant<bool, A<a>::property()>
    {};
    
    template <class T> 
    concept hasProp = HasProp<T>::value;
    
    template <bool a> 
    requires hasProp<A<a>>
    void works(A<a>) {}
    
    template<hasProp C> 
    void deductionError(C){} // no longer a deductionError
    

    Demo


    这确实(可能不必要地)将您的概念与A 直接联系起来。

    您可以改为这样做(例如 @Barry answered):

    template <class T> 
    concept hasProp = T::property();
    

    Demo2

    【讨论】:

    • 这实际上是一个很酷的技巧 :) 感谢您的回答!
    • @mutableVoid:很高兴为您提供帮助。我自己对概念还是很陌生(我们不是吗?)所以我不知道这是否是最佳实现。我确实想指出的一件事是我使用std::conjunction 而不是&amp;&amp;。当您在元编程上下文中使用&amp;&amp; 时,没有短路评估,因此双方总是被评估。 std::conjunction 为我们提供了我们想要的短路评估。
    • 这很酷,我也不知道,我认为这实际上也可能是我刚刚想到的问题的答案:)(我刚开始尝试将一组通过参数包的概念)
    • 你基本上是在 HasProp 上专注于 A&lt;a&gt;... 但你是以一种非常迂回的方式来做这件事的。就做HasProp&lt;A&lt;a&gt;&gt; : integral_constant&lt;bool, A&lt;a&gt;::property()&gt; { };
    • @mutableVoid:标准的编写者很聪明地为约束评估(概念)制定了短路评估标准。在其他元编程环境中,情况并非如此。 Demo
    【解决方案2】:

    你真的需要绑定到A吗?

    template <typename T> concept hasProp = T::property();
    
    template <bool a> requires hasProp<A<a>> void works(A<a>); // ok
    template <hasProp C> void deductionError(C);               // also ok
    

    如果您确实需要搭配,可以将其完全本地添加到 hasProp

    // unfortunately this is hard to generalize due to the non-type template parameter
    template <typename T> struct is_A : std::false_type { };
    template <bool b> struct is_A<A<b>> : std::true_type { };
    
    template <typename T> concept hasProp = is_A<T>::value && T::property();
    
    // ... and the rest works as before
    template <bool a> requires hasProp<A<a>> void works(A<a>); // ok
    template <hasProp C> void deductionError(C);               // also ok
    

    无论哪种方式,hasProp 都应该只是一个类型。

    【讨论】:

    • 感谢您的回答 :)。我认为在应用程序中我真正利用了这个概念,最好明确确保模板的类型等于上面示例代码中由 'A' 表示的类型。但这对我来说是非常有趣的输入,感谢您的建议!我也喜欢这个概念在你的答案部分被划分为“类型检查”和属性的方式,并将在我的代码中改变它:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多