Can (a==1)&&(a==2)&&(a==3) evaluate to true? (and can it be useful?)

前端 未结 8 1347
北荒
北荒 2021-01-15 11:34

Inspired by another question regarding java-script language. Can the expression

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

evaluate to true i

相关标签:
8条回答
  • 2021-01-15 11:59

    Just to show my own ideas. I was thinking of some data structure like a stream buffer or a ring buffer.

    We can with template inheritance "hide away the operator" and nothing will be altered in the data structure in itself but all checking will be done in the template superclass.

    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;
    }
    

    In this case the == to an integer could be a short-cut for "is the next packet/element in the stream of this ID number" for example.

    0 讨论(0)
  • 2021-01-15 12:01

    Can the expression evaluate to true in C++?

    Yes, nothing is impossible...

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

    Then:

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

    prints meow.

    But I have no idea of any practical usage of such weird overloading and, hopefully, will never see such code in production.

    0 讨论(0)
  • 2021-01-15 12:03

    As it was noticed before, this trick could be performed with volatile. This is more honest approach compared to operator changing. Just let us use two threads:

    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;
        }
    }
    

    Moreover, this code in my case is working well with no volatile declaration. As far as I understand, it should depend on compiler and processor. Maybe someone could correct it, if I'm wrong.

    0 讨论(0)
  • 2021-01-15 12:07

    I assume a requirement is a valid program free of undefined behaviour. Otherwise simply introduce something like a data race and wait for the right circumstances to occur.

    In a nutshell: Yes, it is possible for user-defined types. C++ has operator overloading, so the related answers from the JavaScript question apply. a must be a user-defined type because we compare against integers and you cannot implement operator overloads where all parameters are built-in types. Given that, a trivial solution could look like:

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

    Can something like this be useful? As the question is stated: almost certainly not. There is a strong semantic meaning implied by the operator symbols used in their usual context. In the case of == that’s equality comparison. Changing that meaning makes for a surprising API, and that’s bad because it encourages incorrect usage.

    However there are libraries that explicitly use operators for completely different purposes.

    • We have an example from the STL itself: iostream’s usage of << and >>.
    • Another one is Boost Spirit. They use operators for writing parsers in an EBNF like syntax.

    Such redefinitions of the operator symbols are fine because they make it perfectly obvious that the usual operator symbols are used for a very different purpose.

    0 讨论(0)
  • 2021-01-15 12:10

    Other things not mentioned yet (source):

    • a might have overloaded operator int(), the operator for implicit conversion to int (instead of operator== as covered by other answers).
    • a might be a preprocessor macro.

    Example of the latter:

    int b = 0;
    #define a ++b
    if ((a==1)&&(a==2)&&(a==3))
        std::cout << "aha\n";
    
    0 讨论(0)
  • 2021-01-15 12:13

    Yes it can:

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

    Then, let a be of type Foo and voila.

    Can this actually be useful? I don't really see it being useful no.

    0 讨论(0)
提交回复
热议问题