标签: c++-concepts

模板推导与隐式用户定义的转换运算符

我试图实现一个涉及模板的用户定义类型转换的小例子.

#include <cassert>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <type_traits>

template <typename T>
concept bool UIntegral = requires() {
    std::is_integral_v<T> && !std::is_signed_v<T>;
};

class Number
{
public:
    Number(uint32_t number): _number(number)
    {
        if (number == 1) {
            number = 0;
        }

        for (; number > 1; number /= 10);
        if (number == 0) {
            throw std::logic_error("scale must be a factor of 10");
        }
    }

    template <UIntegral T>
    operator T() const
    {
        return static_cast<T>(this->_number);
    }

private:
    uint32_t _number;
};

void changeScale(uint32_t& …
Run Code Online (Sandbox Code Playgroud)

c++ templates implicit-conversion c++-concepts c++20

8
推荐指数
1
解决办法
302
查看次数

为什么C++概念中没有前向声明?

当我尝试这个例子时:

template <typename T>
concept only_int = std::same_as<T, int>;

int add_ints(only_int auto&&... args) {
    return (std::forward<decltype(args)>(args) + ... + 0);
}
Run Code Online (Sandbox Code Playgroud)

它有效......但是当我只像这样声明它时:

template <typename T>
concept only_int;

...

// defined later on...
Run Code Online (Sandbox Code Playgroud)

它会抛出编译错误。

这是缺少的功能吗?还是打算就这样离开?

c++ forward-declaration c++-concepts c++20

8
推荐指数
1
解决办法
1307
查看次数

如何测试概念中是否存在类型?

如何测试概念模板参数中是否存在成员类型,即 for typename Container、 test for Container::reverse_iterator?正确的要求子句是什么?

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

8
推荐指数
1
解决办法
1033
查看次数

如何专门化 std::common_type&lt;A,B&gt; 以便它自然可交换?

std::common_type<T1, ..., TN>T1是 C++ 中的一个辅助模板,它可以找到所有...TN都可以隐式转换为的通用类型。

根据 C++ 规范,如果某些条件适用,用户可以专门化std::common_type<T1,T2>,并且:

std::common_type<T1, T2>::type并且std::common_type<T2, T1>::type必须表示相同的类型。

然而,common_type<T1, T2>对于用户类型来说,可能是一个非常复杂的专业化,T1并且T2

namespace std {

    template <typename T1, complicated_constraint_of<T1> T2, ...>
    struct common_type<complicated_expression_of<T1, ...>, complicated_expression_of<T2, ...>> {
        using type = complicated_type_expression_of<T1,T2>;
    };

}
Run Code Online (Sandbox Code Playgroud)

一般来说,约束表达式不一定是对称的(例如,我们可以指定 是T2的底T1)。这意味着为了保持对称性,我们需要用T1T2反转来重写整个特化,但在不犯任何错误的情况下做到这一点是极其困难和脆弱的。

如何common_type<T1,T2>为我自己的类型稳健地定义 的交换特化?

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

8
推荐指数
1
解决办法
389
查看次数

保持平等和稳定有什么区别?

根据草案

如果给定相同的输入,表达式会产生相同的输出,则该表达式是保持相等的。[ ... ]

[...]稳定:具有相同输入对象的此类表达式的两次评估需要具有相同的输出,而无需对这些输入对象进行任何显式干预修改。[...]

强调我的。

  • 这些有什么区别?

  • 什么时候一个表达式可以保持相等不稳定反之亦然

c++ language-lawyer c++-concepts

7
推荐指数
1
解决办法
532
查看次数

检查概念中的 constexpr

我刚开始做概念。检查表达式的语法非常有用,它为我删除了很多 sfinae 的样板文件。但是我想知道如何检查表达式是否可以在 constexpr 上下文中使用。有时这些表达式会导致无效。我可以想象的方式看起来像这样,没有注释 constexpr 关键字:

template<typename T>
concept foo = requires(T t) {
    /* constexpr */ { t.bar(); } -> std::same_as<void>;
    /* constepxr */ { T::foo; };
}
Run Code Online (Sandbox Code Playgroud)

但是,我非常怀疑这是正确的语法。有没有一种简单的方法来检查概念中表达式的constexpr-ness?

我不想检查 constexpr 函数的计算对于 的所有可能值是否不会失败t,我想知道我是否可以将该表达式放在编译器期望某些东西在编译时可评估的地方。

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

7
推荐指数
1
解决办法
149
查看次数

为什么不接受使用概念的此类专业化?

以下代码尝试使用概念对类进行部分特化,并向特化添加方法,但被 clang 11.0.0 拒绝:

#include <concepts>

template <typename T> // note: previous template declaration is here
struct S {};

template <std::integral T>
struct S<T>
{
    void f();
};

template <std::integral T> // error: type constraint differs in template redeclaration
void S<T>::f()
{
}
Run Code Online (Sandbox Code Playgroud)

clang 给出了错误信息:

<source>:14:16: error: type constraint differs in template redeclaration
template <std::integral T>
               ^
<source>:3:11: note: previous template declaration is here
template <typename T>
Run Code Online (Sandbox Code Playgroud)

(参见https://godbolt.org/z/Wv1ojK)。为什么这段代码是错误的?或者这是clang中的一个错误?(FWIW,此代码被 gcc trunk 和 MSVC 19.28 接受,尽管这不能保证正确性。)

c++ templates template-meta-programming c++-concepts c++20

7
推荐指数
1
解决办法
124
查看次数

为什么std::visit in a unsatisfied concept会导致gcc编译错误

这段代码:

#include <concepts>
#include <string>
#include <variant>

struct any_callable {
public:
    template<typename T>
    void operator()(T&&) {}
};

template<typename V>
concept is_variant = requires(V v) { std::visit(any_callable{}, v); };

int main() {
    constexpr bool wrapped = is_variant<std::string>;
}
Run Code Online (Sandbox Code Playgroud)

不能在 gcc 11 下编译。它给出了一堆关于valueless_by_exception诸如此类的错误。但是,它确实在 msvc ( Godbolt )下编译。现在,据我所知,在这种情况下,如果它通常无法编译,它将衰减为 false,否则为 true。msvc 的行为似乎支持这一点。

所以:这是 gcc 中的错误,msvc 的非标准功能,和/或我的代码有错吗?

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

7
推荐指数
1
解决办法
133
查看次数

C++20 模板模板概念语法

有了概念,C++20提供了很好的语法,比如

template<typename T>
concept SomeConcept = true; // stuff here


template<typename T>
requires SomeConcept<T>
class Foo;

template<SomeConcept T>
class Foo;

Run Code Online (Sandbox Code Playgroud)

其中限制类的两种概念方式是等效的,但后者更简洁。

如果我现在有一些模板模板概念,例如

template<template<typename> typename T>
concept SomeOtherConcept = true; // stuff here

template<template<typename> typename T>
requires SomeOtherConcept<T>
class Foo;
Run Code Online (Sandbox Code Playgroud)

我不知道没有要求子句的非详细(简洁/简短)语法,例如

template<template<typename> SomeotherConcept T>
class Foo;

template<template<SomeOtherConcept> typename T>
class Foo;
Run Code Online (Sandbox Code Playgroud)

没有用,所以

声明这样一个模板模板类的正确语法是什么,对模板模板参数有概念限制?

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

7
推荐指数
1
解决办法
120
查看次数

为什么未验证模板模板参数中的概念?

C++20 允许程序为模板模板参数指定概念。例如,

#include <concepts>

template <typename T> concept Char = std::same_as<T, char>;
template <typename> struct S {};
template <template <Char U> typename T, typename U> T<U> foo() { return {}; }

int main() { foo<S, int>(); }
Run Code Online (Sandbox Code Playgroud)

函数的第一个模板参数foo应该是一个单参数模板。

该概念Char仅被定义为 true 类型char,因此尝试满足它 forint将失败。以上程序被所有编译器接受:https : //gcc.godbolt.org/z/PaeETh6GP

能否请您解释一下,为什么可以指定模板模板参数中的概念,但仍然会被忽略?

c++ contravariance template-templates c++-concepts c++20

7
推荐指数
1
解决办法
163
查看次数