7

Consider the following struct with a single data member and an operator==

struct S {
    int a;
    /*constexpr*/ bool operator==(const S& other) const {
        return this->a == other.a;
    }
};

in its use, two structs can easily be created as constexpr with an initialization list

int main() {
    constexpr S s1 = {1};
    constexpr S s2 = {2};
    constexpr bool b = s1 == s2; // error

    return 0;
}

the bool comparison can't compile because the == operator is not marked as constexpr, When it is, the program compiles.

Should all comparison operators for any class that can be constexpr also be marked as constexpr? I don't see any reason why not, but I also haven't seen code practicing this.

I would also take it a step further and ask if something like operator*(S, S) should be constexpr as well, all the time.

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • 1
    `constexpr` in C++11 imposes tight constraints on the implementation of a function. See the related http://stackoverflow.com/a/20970745/420683 and http://stackoverflow.com/a/5116399/420683 Imagine a string comparison: http://stackoverflow.com/q/20901977/420683 – dyp Jan 20 '14 at 20:44
  • 1
    @dyp constexpr rules are relaxed in C++1y and allow all the loop construct, a constexpr string equality function will looks like an usual non constexpr one in a near future. – galop1n Jan 20 '14 at 20:59
  • If you want those functions to be usable in a constant expression, they must be `constexpr`. If you don't need them usable in a constant expression, it doesn't matter. This is an interface issue just like marking member functions `const` - you should define the interface to support the intended usage. – Casey Jan 20 '14 at 21:00
  • @galop1n See my comment to the question at the third link ;) but for C++11 and to a lesser degree in C++1y, performance might still be an issue. I consider the interface issue more important (e.g. you can't declare it non-constexpr in debug but constexpr in release if someone needs to rely on the constexpr-ness). – dyp Jan 20 '14 at 21:03

3 Answers3

1

The Thing is that comparison is not always the type that the user could use standard comparison operators.Sometimes two objects can be compared and greater than or less Than or equals to can have new definitions .For example in a class that holds objects of type Coordinates Comparison can be defined in a custom way. For example :

Coordinate c1(3,5)
Coordinate c2(4,2)

We can overload the == operator to return True for c1==c2 whenever c1.x == c2.x or c1.y==c2.y or when both expressions are true.

The same goes for constexpr type objects and structs

fer y
  • 505
  • 4
  • 19
0

Should all comparison operators for any class that can be constexpr also be marked as constexpr?

I would also take it a step further and ask if something like operator*(S, S) should be constexpr as well, all the time.

Surely they should, if you want to write nicely usable code.

I don't see any reason why not, but I also haven't seen code practicing this.

To see a good example, take a look at std::pair and std::tuple implementations. However, usually you won't write classes that will be useful as compile-time values.

Community
  • 1
  • 1
lisyarus
  • 15,025
  • 3
  • 43
  • 68
  • *"To see a good example, take a look at std::pair and std::tuple implementations."* Member functions of class templates marked as `constexpr` are *optionally* `constexpr`. I.e. if and only if their function bodies fulfil the `constexpr` requirements, they're *actually* `constexpr`. This is not the case for member functions of ordinary (non-template) classes. See [dcl.constexpr]/6 – dyp Jan 20 '14 at 22:05
  • @dyp: I understand it, but how is it related to the examples I've given? – lisyarus Jan 20 '14 at 22:10
  • 1
    Well `std::tuple` and `std::pair` are class templates...? And they're particularly simple classes, as they're basically just aggregates. There are classes where you *can't* make the comparison operator `constexpr`, e.g. if they need to use a `dynamic_cast`, or where a checked (debug) implementation cannot be `constexpr`. – dyp Jan 20 '14 at 22:15
  • @dyp: yes. it sounds reasonable, thank you. But in cases when the template parameters' methods and operators are constexpr, the corresponding std::tuple's and std::pair's methods/operators will also be constexpr, won't they? – lisyarus Jan 20 '14 at 22:18
  • 1
    Yes, that's what I meant with *optional*. Probably that's the wrong term, something like *if possible* is more appropriate. For example, `std::pair::operator==` is `constexpr` IFF `X::operator==` and `Y::operator==` are `constexpr`. – dyp Jan 20 '14 at 22:23
0

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed.

as stated, if your operator may be used as compile time constant, declare it as constexpr. Otherwise, just save some typing, keep a clean view of code and don't confuse others.

feverzsj
  • 169
  • 2
  • 14