可以(a == 1)&&(a == 2)&&(a == 3)评估为真? (它有用吗?)

时间:2018-01-20 12:29:27

标签: c++ operator-overloading

受另一个关于java-script language的问题的启发。可以表达

 (a==1)&&(a==2)&&(a==3)

在C ++中评估为true? (如果是这样,它真的有用吗?)

8 个答案:

答案 0 :(得分:10)

是的,它可以:

class Foo
{
    public:
    bool operator==(int a)
    {
        return true;
    }
};

然后,让a属于Foo类型,瞧。

这实际上有用吗?我真的没有看到它没用。

答案 1 :(得分:5)

  

表达式可以在C ++中评估为true吗?

是的,没有什么是不可能的......

struct A {
    int x = 0;
};

bool operator==(A& a, int num) {
    return ++a.x == num;
}

然后:

if ((a == 1) && (a == 2) && (a == 3)) {
    std::cout << "meow" << std::endl;
}

打印meow

但是我不知道这种奇怪的重载的任何实际用法,并且希望永远不会在生产中看到这样的代码。

答案 2 :(得分:2)

可能有点用处。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

struct Foo {
    std::vector<int> v = {1,2,3};
};

bool operator==(const Foo& foo, int i) {
    return std::any_of(foo.v.begin(), foo.v.end(), [=](int v){ return v == i; });
}

int main() {
    Foo a;

    if (a==1 && a==2 && a==3)
        cout << "Really??" << endl;
    return 0;
}

答案 3 :(得分:1)

如前所述,这个技巧可以用volatile执行。与操作员更改相比,这更像是诚实方法。让我们使用两个线程:

volatile int a;

void changingValue(){
    std::srand(unsigned(std::time(0)));
    while (true) {
        a = (rand() % 3 + 1);
    }
}

void checkingValue(){
    while (true) {
        if (a == 1 && a == 2 && a == 3) {
            std::cout << "Good choice!" << std::endl;
        }
    }
}

int main() {
    std::thread changeValue = std::thread(changingValue);
    changeValue.detach();
    std::thread checkValue = std::thread(checkingValue);
    checkValue.detach();
    while (true){
        continue;
    }
}

此外,在我的情况下,此代码在没有volatile声明的情况下运行良好。据我了解,它应该依赖于编译器和处理器。如果我错了,也许有人可以纠正它。

答案 4 :(得分:1)

尚未提及的其他事项(source):

  • a可能超载了operator int(),这是用于隐式转换为int的运算符(而不是其他答案所涵盖的operator==)。
  • a可能是预处理器宏。

后者的示例:

int b = 0;
#define a ++b
if ((a==1)&&(a==2)&&(a==3))
    std::cout << "aha\n";

答案 5 :(得分:0)

运算符重载和宏是这种谜语的简单解决方案。

  

如果是这样,它真的有用吗?

嗯,有一些想象......我能想到的一个可能的用例是单元测试或集成测试,你要确保你的某些类的重载operator==正常工作,你肯定知道如果它报告不同操作数的相等性,它不能正常工作:

class A {
public:
    A(int i);
    bool operator==(int i) const;
    // ...
};

A a(1);

if ((a==1)&&(a==2)&&(a==3)) {
    // failed test
    // ...
}

答案 6 :(得分:0)

我假设需求是一个没有未定义行为的有效程序。否则只需引入类似数据竞争的东西,等待正确的情况发生。

简而言之:是的,用户定义的类型是可能的。 C ++有运算符重载,因此JavaScript问题的相关答案适用。 a必须是用户定义的类型,因为我们与整数进行比较,并且您无法实现所有参数都是内置类型的运算符重载。鉴于此,一个简单的解决方案可能看起来像:

struct A {}
bool operator==(A, int) { return true; }
bool operator==(int, A) { return true; }

这样的东西可以用吗?正如问题所述:几乎肯定不是。在其通常的上下文中使用的运算符符号隐含着强烈的语义含义。在 == 的情况下,相等比较。改变这个含义会产生令人惊讶的API,这很糟糕,因为它会鼓励不正确的使用。

但是,有些库明确地将运算符用于完全不同的目的。

  • 我们有一个STL本身的例子:iostream使用<<>>
  • 另一个是Boost Spirit。他们使用运算符以EBNF语法编写解析器。

运算符符号的这种重新定义很好,因为它们非常明显地表示通常的运算符符号用于非常不同的目的。

答案 7 :(得分:-1)

只是为了展示我自己的想法。我在考虑一些数据结构,如流缓冲区或环形缓冲区。

我们可以使用模板继承“隐藏运算符”,数据结构本身不会改变任何内容,但所有检查都将在模板超类中完成。

template<class C>
class Iterable{
 C operator==(int a);
 public:
 Iterable(){pos = 0;}
 int pos;
};
template<class C>
class Stream : public Iterable<Stream<C>>{
public:
  Stream(C a){ m[0] = a; }
  C m[32];
  int operator==(int a){
  return (m[this->pos++]==a);  }
};

int main(){
Stream<int> a(1);
a.m[0] = 1;    a.m[1] = 3;    a.m[2] = 2;
if(a==1 && a==3 && a==2)
    std::cout<<"Really!?"<<std::endl;
return 0;
}

在这种情况下,例如,==到一个整数可以是“是这个ID号的流中的下一个数据包/元素”的快捷方式。