标签: c++20

概念:要求类方法返回类型是同一类的嵌套类型

我正在尝试实现以下概念

template<typename T>
concept GameLogic = requires(T a)  {
    typename T::StateType;
    typename T::EventType;
    { a.initialState()->T::StateType }; // <-- relevant bit
};
Run Code Online (Sandbox Code Playgroud)

我想强制initialState()返回类型是同一类的嵌套类型。

概念定义不会引发错误(gcc 9.2),但以下实现GameLogic无法满足要求:

class SimpleGameLogic {
public:

    using StateType = SimpleState;
    using EventType = SimpleEvent;

    StateType initialState() {
        return _initialState;
    }

private:
    StateType _initialState;

};
Run Code Online (Sandbox Code Playgroud)

我已经尝试了上述语法的一些变体,但找不到正确的语法...或者这可能尚未实现?我究竟做错了什么?

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

0
推荐指数
1
解决办法
245
查看次数

通用“sqr”函数

我试图弄清楚如何为 sqr 运算编写“完全通用函数”(它实际上可以是乘法、除法、加法,并不重要)。

考虑下面的代码

#include <iostream>

struct A
{
    int val = 2;

    A() = default;
    A(const A&) = delete; // To make sure we do not copy anything
    A(A&& a) = delete; // To make sure we do not move anything
    auto operator=(auto) = delete; // To make sure we do not assign anything
    // This is important part, we do not want to create a new object on each multiplication.
    // We want just to update the old …
Run Code Online (Sandbox Code Playgroud)

c++ c++14 c++17 c++20

0
推荐指数
1
解决办法
3079
查看次数

为什么 std::iterator_traits 中的几乎所有类型别名都没有默认值?

在不借助 boost.iterator 等库的帮助下创建 C++20 之前的新迭代器时,有必要指定类型别名difference_typevalue_typepointer和。 根据cppreference 对于 C++20,只需要指定和referenceiterator_categorydifference_typevalue_type这很棒!但是为什么这 3 个别名有默认值呢?

有两件事我不明白(其中一件事在我看来像是一个疏忽):

  1. value_type为什么和没有默认值difference_type?使用类似的东西std::remove_reference_t<reference>作为默认值难道没有意义吗value_type?作为随机访问迭代器的默认设置difference_type,使用采用两个迭代器的运算符的结果类型可以说是有意义的-
  2. C++20 添加了contiguous_iterator_tag. 就像与input_iterator_tagvsforward_iterator_tag一样,我不明白编译器如何正确区分连续迭代器和随机访问迭代器,我想这就是它显然从不选择的原因contiguous_iterator_tag。这是故意的吗?将输入迭代器错误分类为前向迭代器似乎也有些危险,那么为什么不要求程序员自己指定此别名呢?
  3. 在一个有点不相关的说明上,我不确定即使iterator_category程序员已经明确声明了另一个类别,但默默地生成一个值是否是一个好主意,并且为iterator_category它生成一个与看起来完全不同的值concept也很奇怪。考虑这个不切实际的例子:
#include <iostream>
#include <iterator>

// With the == operator, this is an input iterator, but nothing else.
struct WeirdIterator {
    // Not an output iterator because …
Run Code Online (Sandbox Code Playgroud)

c++ iterator language-lawyer c++20

0
推荐指数
1
解决办法
330
查看次数

C++ 概念中的价值评估

如何正确评估概念声明/requires 子句中的值?

考虑一个概念is_red,检查给定类型是否具有color设置为 的静态 cx 成员/*undefined*/::red,其中枚举中的`/ undefined /;

template <typename T>
concept is_red = requires(T) {
   { T::color == decltype(T::color)::red };
};
Run Code Online (Sandbox Code Playgroud)

这显然是错误的,因为它只检查合成是否定义良好。
因此,这不会按预期工作:

namespace apple {
   enum colors{red, green, yellow };

   struct granny_smith{
      constexpr static auto color = colors::green;
   };
}

static_assert(is_red<apple::granny_smith>); // should fail, but it does not using the previous concept implementation
Run Code Online (Sandbox Code Playgroud)

请参阅此处有关 godbolt 的实例。

这是我目前评估概念价值的方式:

template <bool condition>
using if_t = std::conditional_t<condition, std::true_type, std::false_type>;

template <typename T>
concept is_red …
Run Code Online (Sandbox Code Playgroud)

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

0
推荐指数
1
解决办法
561
查看次数

Template function to load big endian from byte array

I'm trying to implement template function, for reading from byte array in big endian order. This is my current implementation:

template<typename T>
T load_big_endian(const unsigned char* buf) {
  T res {};

  std::size_t size = sizeof(T) - 1;

  for (int i = 0; i <= size; i += 1) {
    res |= static_cast<T>(buf[size - i] << (i * 8));
  }

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

Is this a good solution? Or better use a separate functions for each type, like load32_big_endian? And …

c++ c++20

0
推荐指数
1
解决办法
65
查看次数

std::string::resize(smaller_than_capacity) 是否保证现有迭代器仍然有效?

根据cpprefstd::vector::resize明确保证:

当调整到较小的大小时,向量容量永远不会减少,因为这会使所有迭代器无效,而不仅仅是那些会被等效pop_back()调用序列无效的迭代器。

但是,我无法找到从任何类似保证文档std::string::resize

是否 std::string::resize(smaller_than_capacity) 保证现有的迭代器仍然有效?

c++ string standards vector c++20

0
推荐指数
1
解决办法
84
查看次数

使用 std::format 将 time_point 转换为字符串,格式包括日期、时间和亚秒

假设我们有一个简单的函数,它接受一个 std::chrono::time_point 并使用给定的格式化字符串返回一个字符串。像这样:

std::string DateTimeToString(std::chrono::sys_time, const char * szFormat /*= "%Y/%m/%d %H:%M:%S"*/)
Run Code Online (Sandbox Code Playgroud)

根据std::formatter的 cppreference 文档,我们应该能够使用各个标签来创建像2021/03/24 15:36:32.123123. 但是,当 time_point 的持续时间使用微秒(我们必须使用)时,这将引发 format_error。

如果我们将其拆分为单独的调用,以便我们分别使用日期和时间的格式,那么它就可以工作。像这样:

auto tSysTime = std::chrono::system_clock::now();
std::string sTime = std::format("{:%H:%M:%S}", tSysTime.time_since_epoch());
std::string sDate = std::format("{:%Y/%m/%d}", std::chrono::sys_days(std::chrono::duration_cast<std::chrono::days>(tSysTime.time_since_epoch())));
Run Code Online (Sandbox Code Playgroud)

我是否误解了某些东西,或者没有办法为我的目的使用单一格式字符串?请记住,格式字符串是一个可选参数,因此我无法对单个参数的拆分进行硬编码。

我的期望是写

std::format("{:%Y/%m/%d %H:%M:%S}",tSysTime.time_since_epoch());
Run Code Online (Sandbox Code Playgroud)

然而,这崩溃了......

预先感谢您的任何帮助!

编辑:我在 Visual Studio 2019 中使用 /std::c++latest 标志

c++ format c++-chrono c++20

0
推荐指数
1
解决办法
96
查看次数

是否可以在 c++20 中使用比较运算符在枚举值之间建立小于大于顺序的关系

如果我们有一个这样的枚举类


enum class alpha{ a, b, c, d};

Run Code Online (Sandbox Code Playgroud)

是否可以实现一个运算符,在字母表中的字母之间建立排序关系,使得

enum class alpha{ a, b, c, d};

constexpr auto operator <=> (alpha lhs, alpha rhs)
{ 
//how do we achieve this? 
};

#include <gtest/gtest.h>

TEST(alphabet, allows_ordering_comparison) 
{
    EXPECT_TRUE(alpha::a < alpha::b);
} 

Run Code Online (Sandbox Code Playgroud)

小于比较将评估为真。我对此的平庸理解是 enum 是一种偏序。对代码中的错误表示歉意。考虑这个问题

c++ enums partial-ordering spaceship-operator c++20

0
推荐指数
1
解决办法
79
查看次数

std::multimap 等于 _range 和 C++20 std::views::values 不能很好地协同工作

我有以下代码,它可以工作,但是 C++20 版本看起来并不比 C++17 版本好多少。我的猜测问题是multimap equal_range返回 apair并且范围无法确定这是一对有效的迭代器。

有没有办法用更短更好的方式来写这个?

#include <iostream>
#include <map>
#include <ranges>

int main() {
    std::multimap<bool,int> oddness{{false,2}, {true,3}, {true,47}, {false,74656}};
    // nice, does not work:
    // oddness.equal_range(true) | std::views::values;
    // works:
    oddness | std::views::values;

    // working code:
    auto odds = oddness.equal_range(true);
    const auto odds_view = std::views::values(std::ranges::subrange(odds.first, odds.second));
    for (const auto& odd : odds_view) {
        std::cout << odd << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20 std-ranges

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

可以在 C++17 中编译,但不能在 C++20 中编译

我有一个非常简单的代码示例。我可以在 C++17 中编译它,但不能在 C++20 中编译它。为什么不?

struct S
{
    S(const S&) = delete;
    S( S&& ) = default;

    int k;
    int m;
    int n;
};

int main()
{
    S s1{10, 20, 30};
    return s1.m;
}
Run Code Online (Sandbox Code Playgroud)

c++ c++20

0
推荐指数
1
解决办法
83
查看次数