标签: c++-concepts

C++ 概念相同且可赋值

我最近一直在尝试 C++ 概念。我正在尝试以下范围扩展文档中的定义:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4569.pdf

的定义和用法Same让我感到困惑。由于我不知道的原因,作者没有给出明确的定义。所以我正在使用:

template <class T, class U>
concept bool Same()
{
  return std::is_same<T, U>::value;
}
Run Code Online (Sandbox Code Playgroud)

问题是该文档给出了以下定义Assignable

template <class T, class U>
concept bool Assignable()
{
  return Common<T, U>() && requires(T&& a, U&& b) {
    { std::forward<T>(a) = std::forward<U>(b) } -> Same<T&>;
  };
}
Run Code Online (Sandbox Code Playgroud)

它不起作用(在 GCC 6.3 下):一个简单的Assignable<int&, int&&>()概念检查给了我false(我已经验证该Common部分没问题)。我必须更改Same<T&>才能T&使其看起来有效。同样的Same<Type>检查也用在其他一些地方。

我的问题是:

  • 我的定义Same正确吗?
  • 为什么Same<T&>用 代替T&?有什么区别?

谢谢你的帮助。

c++ c++-concepts

2
推荐指数
1
解决办法
1037
查看次数

要求约束必须评估为 bool。所以没有 SFINAE

我对“原子约束”一章很好奇https://en.cppreference.com/w/cpp/language/constraints

它说

替换后 E 的类型必须恰好是 bool。不允许转换

f(0); // error: S<int>{} does not have type bool when checking #1,
          // even though #2 is a better match
Run Code Online (Sandbox Code Playgroud)

哎哟。这意味着在使用 require 子句时没有 SFINAE 机制?这不是很糟糕吗
因为我可以看到某些模板类型在遍历表达式后如何结果为 bool,但其他模板类型却看不到。现在我们又需要使用enable_if和东西了。痛得多?

c++ c++-concepts c++20

2
推荐指数
1
解决办法
775
查看次数

C++ 概念的通配符表示“接受此模板参数的任何内容”

有没有办法允许concept使用模板参数,可以使用提供的任何模板参数?

\n

即模板参数占位符的某种通配符魔法?

\n

一个使用示例:

\n
template<class Me, class TestAgainst>\nconcept derived_from_or_same_as = \n    std::same_as<Me, TestAgainst> ||\n    std::derived_from<Me, TestAgainst>;\n
Run Code Online (Sandbox Code Playgroud)\n

需要上面的内容是因为不幸的是,原始类型的 行为与和 的类类型不同。is_base_ofderived_from

\n

现在我们可以定义一个Pair concept来检查提供的类型:

\n
template<class P, class First, class Second>\nconcept Pair = requires(P p) {\n    requires derived_from_or_same_as<decltype(p.first), First>;\n    requires derived_from_or_same_as<decltype(p.second), Second>;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

用例 [a] - 接受任何有效的As或As子类型对:

\n
// this works well\nvoid doWithPairOfA(const Pair<A, A> auto& p) { /* */ }\n
Run Code Online (Sandbox Code Playgroud)\n

用例 …

c++ templates auto c++-concepts c++20

2
推荐指数
1
解决办法
664
查看次数

为什么 require 子句中的否定表达式需要括号?

以下代码是 -clause 的用法示例requires

#include <type_traits>

template <typename T>
  requires std::is_integral_v<T>
void take_integral(T value);
Run Code Online (Sandbox Code Playgroud)

它接受一个计算结果为bool值的表达式(std::is_integral_v<T>在本例中),并按预期工作。但是,当使用运算符对此类表达式求反时!,会导致编译错误:

#include <type_traits>

template <typename T>
  requires !std::is_integral_v<T>
void take_integral(T value);
Run Code Online (Sandbox Code Playgroud)

来自 GCC 的诊断:

<source>:4:12: error: expression must be enclosed in parentheses
    4 |   requires !std::is_integral_v<T>
      |            ^~~~~~~~~~~~~~~~~~~~~~
      |            (                     )
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

来自 Clang 的诊断:

<source>:4:12: error: parentheses are required around this expression in a requires clause
  requires !std::is_integral_v<T>
           ^~~~~~~~~~~~~~~~~~~~~~
           (                     )
1 error generated.
Compiler returned: …
Run Code Online (Sandbox Code Playgroud)

c++ templates c++-concepts c++20

2
推荐指数
1
解决办法
825
查看次数

为什么概念类模板特化会导致错误

我尝试使用 gcc 10 构建以下内容-std=gnu++20 -fconcepts

\n\n
template <std::signed_integral T>\nclass MyClass{ T a; };\n\ntemplate <std::unsigned_integral T>\nclass MyClass{ T a; };\n
Run Code Online (Sandbox Code Playgroud)\n\n

为什么这段代码会导致以下错误?

\n\n
> declaration of template parameter \xe2\x80\x98class T\xe2\x80\x99 with different constraints\n> 55 | template <std::unsigned_integral T>\n>       |           ^~~\n
Run Code Online (Sandbox Code Playgroud)\n\n

应该没问题吧?

\n

template-specialization class-template c++-concepts c++20 gcc10

2
推荐指数
1
解决办法
314
查看次数

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'

c++ templates c++-concepts c++20

2
推荐指数
1
解决办法
236
查看次数

为什么 GCC 在使用 std::tuple_size::value 的约束上成功,但在使用 std::tuple_size_v 的约束上失败?

在下面的代码中,为什么第二个和第三个概念会产生编译错误?

#include <tuple>

template <class P>
concept IsPair1 = std::tuple_size<P>::value == 2;

template <class P>
concept IsPair2 = std::tuple_size_v<P> == 2;

template <class P>
concept IsPair3 = requires { typename std::tuple_size<P>; } && std::tuple_size_v<P> == 2;

constexpr bool intIsPair1 = IsPair1<int>;  // OK, false

constexpr bool intIsPair2 = IsPair2<int>;  // error: incomplete type 'std::tuple_size<int>' used in nested name specifier

constexpr bool intIsPair3 = IsPair3<int>;  // error: incomplete type 'std::tuple_size<int>' used in nested name specifier
Run Code Online (Sandbox Code Playgroud)
/usr/local/Cellar/gcc/11.1.0_1/include/c++/11.1.0/tuple:1334:61: error: incomplete type 'std::tuple_size<int>' used …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts c++20

2
推荐指数
1
解决办法
360
查看次数

如何使用 Concept 检查函数是否具有准确的返回类型?

有一个std::convertible_to<T>概念是检查调用结果是否可以转换为某种类型。

但我想检查函数是否具有确切的返回类型。我怎样才能做到这一点?

c++ function return-type c++-concepts c++20

2
推荐指数
1
解决办法
1526
查看次数

C++20中模板类的概念

我是模板和概念的高级使用新手,所以这里有一个有点复杂的问题:

  • Traits对每个Source类别的许多特征都有一些概念:

    template<typename _Traits>
    concept Traits = requires
    {
       std::same_as<std::decay_t<decltype(_Traits::token)>, std::string_view>;
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 我有一些模板类使用这个概念来处理object_one各种特征(例如,一半的Source类返回object_one):

    template <concepts::Traits _Traits>
    class Object_one_handler final
    {
        static std::string handle_object(const object_one& obj) {/*...*/}
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 然后我有了来自不同集合的Objects_handlers各种对象的处理程序的概念:{object_one, object_two, object_three}SourcesTraits

    template<template <concepts::Traits _Traits> class _Objects_handlers, typename _Object>
    concept Objects_handlers = requires(const _Object& obj)
    {
       // has handle_object method
       { _Objects_handlers<???????>::handle_object(obj) } -> std::same_as<std::string>;
    };
    
    Run Code Online (Sandbox Code Playgroud)
  • 最后,我创建了一些database指定为模板参数的内容Object_handler

    template<concepts::Objects_handlers _handler>
    class database 
    {...};
    
    Run Code Online (Sandbox Code Playgroud)

(实际上所有概念都有额外的要求,但这里并不重要) …

c++ templates c++-concepts c++20

2
推荐指数
1
解决办法
2392
查看次数

C++ 不同概念的不同 using 声明

比方说,我有我的List<T>课。我有很多函数,我必须传递我T类型的单个对象。例如

void add(const T& item)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

T如果是某个类或结构就有意义。但是,如果T是字节或整数,则通过引用传递它是没有意义的,甚至是错误的,因为内存指针花费 8 个字节(在 32 位系统上为 4 个字节),即我通过 8 字节大小的指针传递 1 字节大小的数据类型。

所以我决定使用using指令定义参数数据类型。有点儿:

using argType = const T&; requires sizeof(T) > 8
using argType = T; requires sizeof(T) <= 8
Run Code Online (Sandbox Code Playgroud)

但是,显然,这段代码不起作用。您能为我提出其他解决方案吗?

c++ optimization micro-optimization c++-concepts c++20

2
推荐指数
1
解决办法
152
查看次数