标签: c++-concepts

为什么 std::erase(std::erase_if) 不是 <algorithm> 中适用于任何容器的模板?

std::erase(_if)是对 C++20 的一个很好的补充(终于我可以忘记令人讨厌的擦除删除习惯用法),但有一点很奇怪:从某种意义上说,它不是一种通用算法,它只适用于 std:: 容器,例如它可以不对升压向量进行操作。

    #include<string>

    #include<vector>

    #include<boost/container/vector.hpp>

    int main() {
        std::string str = " Hello World  !";
        std::erase(str, ' '); // :)
        boost::container::vector<int> vi{1,2};
        std::erase(vi, 2); // :(
    }
Run Code Online (Sandbox Code Playgroud)

我最好的猜测是,该算法早在标准中投票概念之前就已经处于实验状态,因此需要进行大量工作来重新设计它,或者担心无法正确指定它的概念(即它会在某些情况下无法正确工作)具有时髦语义的用户定义类型)。

所以:我的问题是为什么这不是具有某些概念(或enable_if)要求/调度(例如地图/集)的通用算法?

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

3
推荐指数
1
解决办法
248
查看次数

用概念检查属性类型

我想检查结构/类的属性是否符合我的概念需求,但编译器抱怨。

例子:

struct N
{
    char value;
    auto Get() { return value; }
};

struct M
{
    int value;
    auto Get() { return value; }
};

void func3( auto n )
    requires requires
{
    //{ n.Get() } -> std::same_as<int>;
    { n.value } -> std::same_as<int>;
}
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}


void func3( auto n )
    requires requires 
{
    //{ n.Get() } -> std::same_as<char>;
    { n.value } -> std::same_as<char>;
}
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main() …
Run Code Online (Sandbox Code Playgroud)

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

3
推荐指数
1
解决办法
785
查看次数

使用指令不适用于 c++20 概念吗?

using 指令不适用于概念吗?为什么?

下面的示例不起作用,我收到一个编译器错误,提示它需要一个类型。

#include <concepts>

namespace A::X {

  struct BaseA {};

  template < typename AType >
    concept DerivedFromA = std::derived_from < AType, BaseA >;

}

namespace A {

  using DerivedFromA = X::DerivedFromA;

}
Run Code Online (Sandbox Code Playgroud)

我希望能够访问概念DerivedFromA从命名空间ADerivedFromA,而不是X::DerivedFromA

c++ generic-programming c++-concepts c++20

3
推荐指数
1
解决办法
103
查看次数

如何在 C++20“requires”表达式中使用未指定的类型?

我正在尝试编写一个 C++20 概念来表达类型具有某种方法(该方法接受参数)的要求,但出于此概念的目的,我不关心参数类型是什么。

我试着写一些类似的东西:

template <typename T>
concept HasFooMethod = requires(T t, auto x)
{
    { t.Foo(x) } -> std::same_as<void>;
};
Run Code Online (Sandbox Code Playgroud)

然而,gcc 和 clang 都拒绝这一点,并给出一个错误,即“auto”不能以这种方式在 require 表达式的参数列表中使用。

另一种方法是将“x”的类型作为第二个模板参数:

template <typename T, typename TX>
concept HasFooMethod = requires(T t, TX x)
{
    { t.Foo(x) } -> std::same_as<void>;
};
Run Code Online (Sandbox Code Playgroud)

但这需要在使用该概念时明确指定 TX,因此无法推断:

struct S { void Foo(int); };
static_assert(HasFooMethod<S>);         // doesn't compile
static_assert(HasFooMethod<S, int>);    // the 'int' must be specified
Run Code Online (Sandbox Code Playgroud)

有没有办法编写一个允许 Foo 接受未指定类型的参数的概念?

需要约束模板成员函数的概念定义问题非常相似,但不相同:该问题询问如何要求(模板化)方法可以采用满足给定概念的任何类型,而这个问题是关于要求方法采用某种特定类型,尽管该类型未指定。就量词而言,另一个问题是关于(有界)普遍量化,而这个问题是关于存在量化。另一个问题的答案也不适用于我的情况。

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

3
推荐指数
1
解决办法
1313
查看次数

一个概念的lambdification是改进还是不好的做法?

看来您可以将 lambda 放入概念中,然后在其中编写代码。让我们以此为例。我更喜欢这些概念的标准概念,并记住这仅用于此示例的目的 - Godbolt

template<class T>
concept labdified_concept =
    requires {
            [](){                 
                T t, tt; // default constructible
                T ttt{t}; // copy constructible
                tt = t; //copy assignable
                tt = std::move(t); // move assignable
            };
        };
Run Code Online (Sandbox Code Playgroud)

代替:

template<class T>
concept normal_concept = 
    std::default_initializable<T> && std::movable<T> && std::copy_constructible<T>;

Run Code Online (Sandbox Code Playgroud)

羔羊化是一种改进还是不好的做法?从可读性的角度来看也是如此。

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

3
推荐指数
2
解决办法
139
查看次数

表达概念中数据成员的概念要求的最佳方式是什么?

为该类型的数据成员定义具有嵌套概念要求的概念的最佳方法是什么?沿着这些路线的东西:

template<typename T>
concept MyConcept = requires(T a) {    
    {a.something} -> std::integral;
};
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为a.something它被作为参考 ( delctype((a.something)))选取。我想出的最好的作品是这样的东西,它强制一个右值:

constexpr auto copy = [](auto value) { return value; };

template<typename T>
concept MyConcept = requires(T a) {    
    {copy(a.something)} -> std::integral;
};
Run Code Online (Sandbox Code Playgroud)

我有更好的选择吗?

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

3
推荐指数
1
解决办法
101
查看次数

可选类型名是否适用于概念?

GCC 实现了P0634R3,它放弃了指定typename类型何时在已知上下文中的需要。

是否也适用concept

因为下面的代码不能编译:

template<typename T>
concept sample_concept =
    std::default_initializable<T::value_type> &&
    requires (T t) {
        { t.some_func(std::declval<T::some_type>()) }
            -> std::same_as<T::iterator>;
    };
Run Code Online (Sandbox Code Playgroud)

但是当我typenameT::value_typeand前面指定时T::iterator,它会编译。

c++ language-lawyer c++-concepts c++20

3
推荐指数
1
解决办法
99
查看次数

c ++ 20 如何创建一个约束元组,如只包含允许的类型和自身实例的容器

想象一下,我想制作一个像模板容器这样的元组作为 api 接口的一部分。我想将它限制为允许的类型列表加上这个模板容器的一个实例。现在我有这样的事情:

#include <string>
#include <tuple>
#include <utility>
#include <type_traits>

template<typename T>
constexpr const bool bIsAllowedType =
    std::is_same<T, bool>::value ||
    std::is_same<T, void*>::value ||
    std::is_same<T, double>::value ||
    std::is_same<T, int64_t>::value ||
    std::is_same<T, std::string>::value;

template<typename T, typename... Args>
constexpr const bool bIsAllowedArgList =
    bIsAllowedType<std::remove_reference_t<T>> &&
    bIsAllowedArgList<Args...>;

template<typename T>
constexpr const bool bIsAllowedArgList<T> =
    bIsAllowedType<std::remove_reference_t<T>>;

template<typename... Args>
concept CAllowedArgList =
    bIsAllowedArgList<Args...>;

template<CAllowedArgList... Args>
class Container
{
private:
    using TupleT = std::tuple<std::decay_t<Args>...>;
    TupleT data;
public:
    Container() = default;
    Container(Args&&... args) : data(std::forward<Args>(args)...) {}
}; …
Run Code Online (Sandbox Code Playgroud)

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

3
推荐指数
1
解决办法
92
查看次数

C++20 概念检查类似元组的类型

我想为类似元组的类型创建一个概念。类似元组的类型将是类似于std::pair,std::tuple和 的东西std::array,提供编译时已知数量的类型,可通过编译时索引get<size>函数访问。

我是新概念,我不知道从哪里开始。不幸的是,STL 在<concepts>头文件中似乎没有这样的概念。

例如,我可以写:

template<typename T>
concept tuple_like = requires(T value)
{
    std::invoke(get<0>, value);
};
Run Code Online (Sandbox Code Playgroud)

但我不确定如何将其概括0为任何索引。

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

3
推荐指数
2
解决办法
179
查看次数

将模板参数限制为仅接受具有 C++20 概念的 std::vector 和 std::list

我正在尝试编写一个仅对 std::vector 或 std::list 中的数字进行排序的程序,我为此做了两个概念:

template<typename T>
concept ValidContainer = requires(T a) {
    std::same_as<T, std::vector<typename T::value_type>>;
    std::same_as<T, std::list<typename T::value_type>>;
};
Run Code Online (Sandbox Code Playgroud)

和:

template<typename T>
concept Sortable = requires(T a) {
    ValidContainer<T> && std::same_as<typename T::value_type, int>;
    ValidContainer<T> && std::same_as<typename T::value_type, float>;
};
Run Code Online (Sandbox Code Playgroud)

以及对它们进行排序的函数的签名:

void BubbleSort(Sortable auto& collection)
{
    // sort algorithm
}
Run Code Online (Sandbox Code Playgroud)

我脑海中出现的问题是,当我传递 a 时,std::vector<std::string>它没有显示编译错误?

int main()
{
    std::vector<int> test = { 32, 3, 6, 8, 2, 5, 0, 43, 67, 1 };
    std::vector<std::string> test2 = { "first", "second", "third" …
Run Code Online (Sandbox Code Playgroud)

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

3
推荐指数
1
解决办法
1297
查看次数