通过隐式转换小于运算符?

时间:2015-12-29 09:17:26

标签: c++ implicit-conversion stl-algorithm c++17 c++-concepts

考虑以下课程:

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

我的问题是:

  • C是否可用于目前使用默认< std::sort的标准算法。操作者?
  • C被视为满足LessThanComparable概念吗?
  • C是否符合假设的特定算法库的要求,该算法要求类型为LessThanComparable

3 个答案:

答案 0 :(得分: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) );
}

编译。 Here's a live demo.看看下一个问题!

  

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

没有。 LessThanComparable概念的要求是,对于xy类型的对象Cconst C,表达式x<y是有效且隐式的可转换为bool,<运算符建立严格的弱排序关系。在你的情况下,const对象不会转换为int s。这是代码中的错误,因为它不是const正确的。添加const关键字会使其有效,而班级C确实会LessThanComparable。严格的弱顺序关系得以实现,因为int满足了这个要求。

  

C是否符合假设的概念算法的要求   需要类型为LessThanComparable的库。

如果你修复你的常数,是的,它会。

一些旁注:

  • 即使x<yx的类型为y,GCC 4.9也会对const C进行编译。这似乎是一个编译器错误,因为GCC 5.2和clang 3.6在这里抛出编译时错误。

  • std::less<C>()作为额外参数传递给std::sort()会产生编译时错误,因为比较函数要求常量对象在这种情况下具有可比性。但是,传递std::less<void>()并不会破坏任何内容,因为参数完全转发。

  • std::sort() algorithm不需要完整的LessThanComparable,而是概念Compare。此外,迭代器类型必须是RandomAccessIterator ValueSwappable且取消引用类型必须是MoveContructableMoveAssignable。对于第一个问题,这就是所有情况,即使constness bug没有修复。这就是std::sort()和其他标准算法有效的原因。

答案 1 :(得分:3)

没有。编译器无法做到这么大的魔力,即调用强制转换方法然后应用<运算符。想象一下,有几种不同类型的强制转换操作符,编译器如何选择合适的?

编辑:其实这不正确。只要有单一的演员,这就行了。但是有两个或更多的编译器会抱怨模糊的演员。但是,这种方法非常脆弱,所以一般来说这不是一个好主意。

答案 2 :(得分: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;
    }
}

Live Demo

因为这会导致含糊不清。所以,这样做不是一个好主意。