标签: c++-concepts

为什么我不能限制一个概念

不允许这样约束一个概念:

template<typename T>
concept A = expr_1;

template<A T>
concept B = expr_2;   // error
Run Code Online (Sandbox Code Playgroud)

然而,似乎总是可以达到相同的结果,如下所示:

template<typename T>
concept A = expr_1;

template<typename T>
concept B = A<T> && expr_2;   // ok
Run Code Online (Sandbox Code Playgroud)

如果第一个版本总是可以重写为第二个版本,那么为什么不允许第一个版本呢?

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

4
推荐指数
1
解决办法
1078
查看次数

C++20 概念如何定义带参数的函数的存在?

在 C++20 中,我们现在可以使用概念而不是 SFINAE 来确定模板类型名中是否存在函数:

template<typename T> concept fooable = requires (T a) {
    a.foo();
};

class Foo {
public:
    // If commented out, will fail compilation.
    void foo() {}
    void bar() {}
};

template <typename T> requires fooable<T>
void foo_it(T t) {
    t.bar();
}

int main()
{
    foo_it(Foo());
}
Run Code Online (Sandbox Code Playgroud)

我们如何使用具有非空参数的函数来做到这一点?

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

4
推荐指数
1
解决办法
3009
查看次数

如何使用类型特征和概念检测指向算术类型的指针?

如何编写检测指向算术类型的指针的概念?

template <typename T>
concept arithmetic = std::is_arithmetic<T>::value;

template <typename T>
concept pointer_to_arithmetic = requires (T a) {
    { *a } -> arithmetic;
};

template <typename T>
void fn() {
    printf("fail\n");
}   

template <pointer_to_arithmetic T>
void fn() {
    printf("pass\n");
}   

struct s{};

int main() {
    fn<int>();
    fn<int*>();
    fn<s>();
    fn<s*>();
}
Run Code Online (Sandbox Code Playgroud)

我试过上面的,它编译但没有做它应该做的。

预期输出为:

fail
pass
fail
fail
Run Code Online (Sandbox Code Playgroud)

相反,我得到:

fail
fail
fail
fail
Run Code Online (Sandbox Code Playgroud)

如果我替换*aa[0].

c++ type-traits c++-concepts c++20

4
推荐指数
1
解决办法
78
查看次数

c++ 概念是否会导致编写模板实例以构建输出?

对于具有许多大型和复杂模板实例的库,在我看来,决定是否使用概念的主要考虑因素之一是构建输出的大小是否更小。

使用 SFINAE,我的理解是以下代码将导致模板实例化std::is_function<bar>std::enable_if<true, bool>包含在构建输出中,增加其大小(尽管对于此示例来说是微不足道的):

#include <type_traits>

template<typename F,
         typename = std::enable_if_t<
                    std::is_function<F>::value,
         bool> = true>
void foo(F& f)
{
    // do some stuff with f
}

void g();

int main()
{
    foo(g);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果使用基于的 C++20 概念std::is_function,显然模板必须被实例化以检查它。但是那个实例化然后写入最终的构建输出吗?这是否因编译器实现而异?

#include <type_traits>

template<typename F>
concept Function = std::is_function<F>::value;

template<Function F>
void foo(F& f)
{
    // do some stuff with f
}
//...
Run Code Online (Sandbox Code Playgroud)

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

4
推荐指数
1
解决办法
69
查看次数

C++20 概念布尔可测试的奥秘

C++20引入了一个比较概念boolean-testable,但是我注意到它的斜体和中间的连字符,说明它只是为了exposition-only,由于没有所谓的std::boolean_testablein <concepts>,我们自己也不能使用代码。

这个仅用于展示的概念的目的是什么?为什么这个概念如此神秘?

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

4
推荐指数
2
解决办法
227
查看次数

未能在 SFINAE 中将概念类型识别为 bool

考虑这个例子:

#include <iostream>
#include <utility>

template<typename T>
concept Printable = requires(const T a) {
    a.print();
};
template<typename T>
constexpr auto is_printable() {
    return Printable<T>;
}

template<class T, std::enable_if_t<is_printable<T>()>* = nullptr>
constexpr void do_print(T data) {
    data.print();
}

struct foo {
    void print() const {
        std::cout << "Hello World\n";
    }
};

int main() {
    foo f;
    do_print(f);
}
Run Code Online (Sandbox Code Playgroud)

尝试在 MSVC(版本 16.9.4,/std:c++latest)上编译它会产生以下错误:

Error   C2783   'void do_print(T)': could not deduce template argument for '__formal'
Error   C2672   'do_print': no matching overloaded function found
Run Code Online (Sandbox Code Playgroud)

它未能满足 …

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

4
推荐指数
1
解决办法
86
查看次数

如何创建共享概念的对象向量?

我想创建一个包含不同类型但共享相同概念的对象的向量(或数组)。
类似于Vec<Box<dyn trait>>Rust。

struct Dog {
    void talk() {
        std::cout << "guau guau" << std::endl;
    }
};

struct Cat {
    void talk() {
        std::cout << "miau miau" << std::endl;
    }
};

template <typename T>
concept Talk = requires(T a) {
    { a.talk() } -> std::convertible_to<void>;
};

int main() {
    auto x = Dog{};
    auto y = Cat{};

    ??? pets = {x, y};

    for(auto& pet: pets) {
        pet.talk();
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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

4
推荐指数
1
解决办法
368
查看次数

C++20 概念的用例是什么?

我在回顾 C++20 特性时发现了概念。我发现他们向模板参数添加了验证,但除此之外,我不明白 C++20 概念的真实用例是什么。

C++ 已经有类似的东西std::is_integral,它们可以很好地执行验证。

我确定我遗漏了一些关于 C++20 概念及其支持的内容。

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

4
推荐指数
1
解决办法
141
查看次数

C++ 概念可以用于在 C++ 中实现混合类型 min 和 max 吗?

您可能知道std::maxstd::min“受苦”,因为它们有 1 个模板参数,因此即使简单max(container.size(), 47)也行不通,因为 .size() 返回size_t而 47 是int

我知道历史上曾有人提议向 C++ 添加适当的重载,但被拒绝了。但据我所知,这主要是由于纸张过于复杂而无法获得足够的收益,所以我想知道是否可以将其std::common_range_t用作返回值(发明的类型特征使您的 int/float 足够大以容纳混合参数的最小值/最大值,否则会出现硬错误)那会好吗...

所以最终得到我的问题:如果我们希望 min/max 扩展为采用 2 如上所述的模板参数,是否有任何向后兼容性或任何其他问题阻止了这一点?

笔记:

  • 这主要是技术上可能的问题,我对 WG21 是否计划做任何事情来标准化这个问题感兴趣,主要是对潜在的技术限制感到好奇。
  • 这个问题的 C++17 版本(由于某种原因被严重低估),但更一般的是,还涉及其他一些限制。

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

4
推荐指数
1
解决办法
98
查看次数

在 C++20 中什么时候应该使用 `iterator_traits&lt;I&gt;::value_type`,什么时候应该使用 `iter_value_t`?

C++20 概念添加了一种访问迭代器特征的替代方法。例如iter_value_t<I>给出与 类似的结果iterator_traits<I>::value_type我注意到iterator_traits在概念约束中似乎不起作用。 iter_value_t适用于概念,但也适用于其他任何地方。所以我的预感是我应该使用较新的,iter_value_t因为它适用于两种情况。

这样对吗?我什么时候应该更喜欢其中一个?

编辑:typename在概念约束中使用 iterator_traits 时我丢失了。这些概念让我感到不安!

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

4
推荐指数
2
解决办法
106
查看次数

标签 统计

c++ ×10

c++-concepts ×10

c++20 ×10

comparison ×1

sfinae ×1

templates ×1

type-traits ×1