16

考虑以下类:

struct C 
{
     /* Class contents, without any arithmetic operator... */
     constexpr operator int() noexcept; // Implicit conversion to int
};

我的问题是:

  • std::sortC 是否可用于当前使用默认 < 运算符的标准算法?
  • C是否被认为满足了这个LessThanComparable概念?
  • C 是否满足要求类型为LessThanComparable.
4

3 回答 3

12

是否可用于当前使用默认运算符C的标准算法?std::sort<

是的,它适用于std::sort()其他一些标准算法。编码

#include <algorithm>
#include <vector>

struct C 
{
     /* Class contents, without any arithmetic operator... */
     constexpr operator int() noexcept {return 0;} // Implicit conversion to int
};

int main()
{
    std::vector<C> v;  
    std::sort( begin(v), end(v) );
}

编译。这是一个现场演示。不过看下一个问题!

是否C被视为满足LessThanComparable概念?

不。这个LessThanComparable概念的要求是,对于对象xy类型Cconst C表达式x<y是有效的,并且可以隐式转换为 bool,并且<运算符建立严格的弱排序关系。在您的情况下, const 对象不会转换为ints。这是您的代码中的一个错误,因为它不是 const 正确的。添加const关键字将使其工作,并且该类C确实是LessThanComparable. 满足严格的弱排序关系,因为ints 满足这个要求。

C满足要求类型为LessThanComparable.

如果你修复你的 constness,是的,它会的。

一些旁注:

  • GCC 4.9 编译x<y即使xyconst C. 这似乎是一个编译器错误,因为 GCC 5.2 和 clang 3.6 在这里抛出了编译时错误。

  • std::less<C>()作为一个额外的参数传递给std::sort()编译时错误,因为比较函数需要常量对象在这种情况下是可比较的。但是,传递std::less<void>()不会破坏任何东西,因为参数是完美转发的。

  • std::sort()算法不需要完整,LessThanComparable但需要概念Compare。此外,迭代器类型必须是 a RandomAccessIteratorthat isValueSwappable并且取消引用的类型必须是MoveContructableand MoveAssignable。这就是您的第一个问题的全部情况,即使没有修复 constness 错误。这就是std::sort()其他标准算法起作用的原因。

于 2015-12-29T09:47:06.427 回答
3

不,编译器不能做这么大的魔术,即调用 cast 方法然后应用<运算符。想象一下,对于不同的类型有几个强制转换运算符,编译器将如何选择正确的一个?

编辑:实际上这是不正确的。只要有单转换运算符,这将起作用。但是有两个或更多编译器会抱怨模棱两可的演员表。但是,这种方法非常脆弱,因此一般来说这不是一个好主意。

于 2015-12-29T09:24:56.707 回答
2

我尝试了mehrdad momeny提出的示例。它工作得很好。然而,几乎没有编辑,它不再工作了。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

struct C 
{
    C(int x):X(x){}
    operator int() { return X; }
    operator float() { return static_cast<float>(X); }

    int X;
};

using namespace std;

int main()
{
    vector<C> u = {1, 2, 35, 6, 3, 7, 8, 9, 10};
    sort(u.begin(), u.end());
    for(auto x: u){
        cout << x << endl;
    }
}

现场演示

因为这会导致歧义。因此,这样做并不是一个好主意。

于 2015-12-29T09:30:27.007 回答