【问题标题】:C++20 concepts: int not swappable_with intC++20 概念:int not swappable_with int
【发布时间】:2020-09-28 16:01:06
【问题描述】:

我正在尝试 C++20 的概念,std::swappable_with 未定义(Visual Studio,使用 /std:c++latest)或其约束与下面的 MCVE 不匹配(g++10 使用 -std=c++2a) -- 也就是说,int 不能与int (!) 交换。有什么办法解决这个问题?如果int 不能与int 交换,我看不到任何东西 工作。

#include <concepts> 

template <typename T, typename U>
requires std::swappable_with<T,U>
void mySwap(T& t, U& u)
{
    T temp = t; t = u; u = temp;
}

int main()
{
    int x, y;
    mySwap(x, y);

    return 0;
}

【问题讨论】:

  • std::is_swappable_with_v&lt;int, int&gt; 给我 0 与 libstdc++:godbolt.org/z/n4U-W6
  • 我没有 C++20,但你可以检查一下:std::is_copy_assignable::value 两种类型,然后交换。如果没有什么对你有用。

标签: c++ c++20 c++-concepts


【解决方案1】:

std::swappable_with&lt;T, U&gt; 检查是否可以使用参数std::declval&lt;T&gt;()std::declval&lt;U&gt;() 调用swap(在using std::swap; 之后)。由于TUint,两个参数都是右值,不能绑定到std::swap 参数,因为它们是(非常量)左值引用。


你想知道int 不能与int 交换——没错,你不能写std::swap(1, -1);

【讨论】:

  • 这太疯狂了。在这种详细程度和深奥的理论中,这些功能的一般用户应该考虑什么?如果您有两个 int 对象,它们肯定是可交换的(这是 std::swap 的典型示例!)所以 std::swappable_with&lt;int, int&gt; 失败是令人难以置信的。谁想出了这些功能?‍♂️
  • @AsteroidsWithWings 如果你有两个 int 对象,它们肯定是可交换的。 — 这不是真的。仅当这两个对象都是左值时才成立。如果两者都是右值,或者一个是右值,第二个是左值,则它们不可交换(使用std::swap)。
  • @AsteroidsWithWings:“这些功能的普通用户在这种详细程度和深奥的理论中应该有什么想法?”当“详细程度和深奥的理论”时会发生什么理论”变得相关?能够区分对左值和右值的操作很重要。特别是在这种情况下,如果用户按值而不是按引用获取TU,会发生什么情况?该函数会编译,但它不会做一些有用的事情。所以在某种程度上,用户已经必须知道一些“深奥的理论”。
  • @NicolBolas 一种明智的语言首先应该具有表达性并且易于用于常见/显而易见的情况,复杂性是可选的额外内容。 C++ 早就忘记了这一点。
  • 公平地说,我要说的一件事可以缓解这种情况,那就是is_swappable&lt;T&gt;(代表is_swappable_with&lt;T&amp;, T&amp;&gt;!)似乎为常见/明显的情况提供了“富有表现力且易于使用" 角度
【解决方案2】:

使用std::swappable_with&lt;T&amp;,U&amp;&gt; - 可交换,关心值类别、按引用编码以及类型。

您实际上是在询问 int 类型的右值是否可以交换。它说“不”;你不能换成右值ints。

这可能会令人困惑,但如果你这样做:

template <class T, class U>
requires std::swappable_with<T,U>
void mySwap(T&& t, U&& u) {
  auto temp = std::forward<T>(t);
  t = std::forward<U>(u);
  u = std::move(temp);
}

它变得更自然一些。在这里,我们使用转发引用,参数的左/右值类别分别存储在TU 中的裸类型旁边。

请注意,如果该类型的对象彼此为swappable_with,则上述可能允许交换右值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    相关资源
    最近更新 更多