简体   繁体   中英

C++ accepts wrong return-type

I have the following code, which, in my opinion, should not compile: (In a class Vector ( not the std::vector , but a Vector that I defined myself)):

Vector operator*(double factor)
{
  // some element-wise multiplication here
  return factor;
}

I am defining this operator to return a Vector , but inside the method i return a double .

I also have not defined any implicit conversion operators inside the class.

I would think that this is clearly not valid, but gcc happily compiles this, without any complaint at all.

My first reflex is to file a defect-report to gcc, but I thought I would ask here before..

Am I missing something here that would explain why this code is considered valid by the compiler?

(In case it's relevant, c++-standard is set to c++17)

Some more Info on the Vector class: (namely, I include all declared constructors and operators, as other, named functions should not contribute to this issue):

class Vector {
public:
  Vector(std::vector<double> values);
  Vector(size_t dimension, double value);
  Vector(size_t dimension);

  void operator*=(double factor);
  void operator*=(Vector const& factor);

  friend Vector operator-(Vector const& a, Vector const& b);
  friend Vector operator+(Vector const& a, Vector const& b);
  friend Vector operator*(Vector const& a, Vector const& b);

  Vector operator*(double factor);
  double& operator[](size_t i);

  friend std::ostream& operator<<(std::ostream& stream, Vector const& v);
}

Basing this answer on received comments:

Non-explicit conversion-operators are not the only way in which a return-value that initially has the wrong type may "become" the type needed for the function-signature. The constructor

Vector(size_t dimension);

Takes one numerical value as an argument, which itself is not a double , but a long unsigned int , but a double can be converted into that.

So what happens is that the double factor is first converted into a long unsigned int and then an implicit construction of Vector , using the constructor Vector(size_t dimension); happens. The object that is the result of this construction is then returned.

Therefore, this is valid code in the sense of not breaking language-rules, the compiler is definitely not doing anything wrong here.

If this behaviour is not wanted, the constructor in question should be marked explicit like this:

explicit Vector(size_t dimension);

If there were multiple constructors taking one argument of a type into which a double can be converted, or whose first arguments fulfill that requirement with all other arguments being optional, for example:

Vector(int a, char b = 'c');

they would have to be marked explicit as well, but in that case it is likely that the compiler would complain, because it could not deduce which constructor to call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM