14

Why is following code not compilable (gcc-5.4.0)?

volatile int i{100};
int j{200};
std::cout << std::min(i, j);

I mean I see the compiler error:

error: no matching function for call to ‘min(volatile int&, int&)’

Isn't volatile just hint to compiler, that the variable could change from outside of the program?

std::min(int(i), j);

Is of course working. But shouldn't original work too?

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
Libor Tomsik
  • 668
  • 7
  • 24
  • 9
    It's worth pointing out that volatile is one of the most mis-understood keywords in the c++ language... and that you should be sure you need it before you use it (not suggesting that you don't need it in your case, there's not enough information - just putting in a word of warning). – UKMonkey Nov 28 '17 at 12:15
  • You know that volatile has nothing to do with threads? –  Nov 28 '17 at 12:15
  • 3
    @UKMonkey: Indeed. When I was young and naughty I'd use it to distinguish parameters when overloading functions. My wrist still hurts from the code reviews. – Bathsheba Nov 28 '17 at 12:15
  • 3
    @Bathsheba you and StoryTeller were talking about vomiting ... my turn – UKMonkey Nov 28 '17 at 12:16
  • Just another c++ standard library design mistake! As pathetical as libc. – Oliv Nov 28 '17 at 14:14
  • @Oliv: the problem is not it is a design mistake. The problem is that they don't fix it. https://stackoverflow.com/a/47398177/8157187 – geza Nov 28 '17 at 17:00
  • @Oliv - `std::min` returns a reference to the result. There is no way to do that and have different parameter types. – StoryTeller - Unslander Monica Nov 28 '17 at 17:01
  • Howard should restart a new library! Long live the Howard! (it's own ward!) – Oliv Nov 28 '17 at 17:21

2 Answers2

24

volatile is a qualifier just like const. It's more than a mere hint to the compiler.

std::min expects the two parameters to have exactly the same types and qualifiers. So in your case it issues a diagnostic.

Since you are allowed to introduce qualifiers, you could indulge in a little hand-holding and write

std::min<volatile int>(i, j)
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
12

As @Bathsheba pointed out, type deduction on the two arguments must give the same type.

But for the sake of completeness std::min is also overloaded to accept a std::initializer_list. The elements of it are subject to copy initialization, so top level cv-qualifiers are immaterial. So this will work:

std::cout << std::min({i, j});

Just bear in mind that it performs copies, and doesn't accept or return references.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458