Can't initialize std::function with comparator

  • A+
Category:Languages

In my C++ class we are learning to use function objects and the like, but now we got a code snippet that works on teacher's compiler (MSVC) but not on ours (we use different OS's).

We tested the code snippet below with several compilers (gcc, clang) and they all reject it, a bit minimized:

#include <functional>  struct Fraction {   Fraction();   Fraction(int z, int n);   Fraction(Fraction&);    // various data members };  struct FractionComparator {   int operator()(Fraction a, Fraction b) {     return 1;   } };  int main() {   std::function<int(Fraction, Fraction)> comparator = FractionComparator(); } 

We get on clang on macOS:

No viable conversion from 'FractionComparator' to 'function<int (Fraction, Fraction)>' 

We already found out that adding a move constructor solves the problem, but we have no idea why this difference exists and why this code doesn't compile on our compilers.

Any ideas?

 


Why adding a move-constructor solves the problem?

Fraction is attempted to be copy-constructed from an rvalue.

But constuctor Fraction(Fraction&); takes a non-constant reference. Non-const references are not allowed to bind to temporaries. The proper constructor signature should be:

Fraction(const Fraction&); 

When you declare a move constructor compiler will move-construct Fraction from an rvalue instead.

Why this code doesn't compile on our compilers, but compiles on teacher's?

This code compiles with VC++. It looks like the compiler is not conforming to the standard here. I could find this StackOverflow question with some more detail. It seems to be a compiler extension that allows this to compile. If compiler extensions are disabled via /Za flag it will not compile anymore.

Typical Microsoft's EEE in action...

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: