I have been looking through source code trying to learn more about C++ and I came across some code that looked confusing. I haven't been able to figure out its use by playing around with it.
Please can someone explain what the operator float *() does and how it is used?
class Vector
{
public:
float x,y,z;
Vector() : x(0), y(0), z(0){
}
Vector( float x, float y, float z ) : x(x), y(y), z(z){
}
operator float*(){
return &x;
}
operator const float *(){
return &x;
}
I have searched StackOverflow and it looks like it is a conversion operator but I am still unsure what it actually does and why it is useful.
Kind regards,
operator type_name declares an implicit conversion operator. In other words, this function is called when you are attempting to (implicitly) convert an object of your type to float* – for instance in an assignment:
Vector x(1, 2, 3);
float* f = x;
assert(*f == 1);
Needless to say, this particular conversion is quite terrible because its effect is pretty unintuitive and easily results in impossible to find bugs. Implicit conversions should generally be handled with care since they hide potentially confusing semantics. But they can be used well with types which are supposed to be used interchangeably, and where a conversion doesn’t hurt.
For instance, consider the case where you write your own integer and complex classes. A conversion from integer to complex is harmless, since every integer is a complex number (but not vice-versa). So having an implicit conversion integer → complex is safe.
As it was said it is a conversion operator that converts an object of type Vector to an object of type float *. This conversion operator can be called implicitly because it has no function specifier explicit.
I think that the idea of introducing this operator was to access data members x, y, z as an array of floats. In this case you could apply some standard algorithms to an object of the class converting it to an array of floats.
Take into account that the second overloaded operator-function shall have qualifier const.
Consider the following code
#include <iostream>
#include <algorithm>
class Vector
{
public:
float x,y,z;
Vector() : x(0), y(0), z(0){
}
Vector( float x, float y, float z ) : x(x), y(y), z(z){
}
operator float*(){
return &x;
}
operator const float *() const {
return &x;
}
};
int main()
{
Vector v( 1, 3, 2 );
auto max = std::max_element( v + 0, v + 3 );
std::cout << *max << std::endl;
return 0;
}
The output is 3.
Take into account that according to the C++ Standard
13 Nonstatic data members of a (non-union) class with the same access
control (Clause 11) are allocated so that later members have higher
addresses within a class object
So the order of the data members of the class is defined.
It's a conversion operator allowing the class to be used with APIs that want a float*.You have two different versions because one will convert the class to a const float* and the other to a non-const. The non-const conversion operator breaks your class's encapsulation though.
Usefulness: Well it can be very handy when, as I mentioned, you want to work with a library that expects a certain type. It can also be useful when there is a natural conversion between two types.
Related
I'm reading this tutorial on computer graphics, and ran across the following code example.
template<typename T>
class Vec3
{
public:
// 3 most basic ways of initializing a vector
Vec3() : x(T(0)), y(T(0)), z(T(0)) {}
Vec3(const T &xx) : x(xx), y(xx), z(xx) {}
Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {}
T x, y, z;
};
typedef Vec3<float> Vec3f;
Vec3<float> a;
Vec3f b;
I recognize that each constructor is making use of member initializer lists.
The default constructor initializes x, y, and z as 0 of type T
?
The constructor accepts x, y, and z explicility and initializes the member variables accordingly.
I'm not sure what 2. is trying to illustrate, or how I would use it. What does const T &xx mean exactly? I get that xx is a pointer to some variable of type T, but is the const referring to the pointer itself or the variable it's pointing to? Furthermore, what's the point of initializing x, y, and z with the same variable?
const T &xx is a reference (&) to a const T.
By using a reference instead of simply passing T xx, a potentially expensive copy can be avoided, in case T is a complex type. (Might be premature optimization in this case, because your typical Vec3 will only be instantiated with types like float or double, but the compiler will optimize it out anyway.)
By making it a reference to a const T, the caller can be certain that the T they pass in will not be modified by the constructor. Moreover, the caller will be able to pass values that are already const, like literals (e.g. Vec3<double>(1.0)).
The rule with const is: it always refers to the thing that precedes it. So int const *x means that x is a (mutable) pointer to a const int, whereas int *const x means that x is a const pointer to a (mutable) int. int const *const x is also possible.
But what if the const is the first token in the type, so there's nothing that precedes it? Then it "jumps over one", so const T &xx is the same as T const &xx. For consistency, I prefer to write the latter, but many people use the former because it reads more naturally from left to right.
This constructor would be useful if you want a vector set to (1, 1, 1), for instance. Of questionable mathematical meaning, but sometimes useful. For example, by multiplying a vector (x, y, z) by (1, 1, 1) we can easily compute the sum of the components of the former vector.
I am translating a java program to C++, and the architecture requires me to return a null pointer at certain points.
I have a pointer constructed as such:
auto p= std::make_unique< std::array< A, 3>>();
where A is of the form:
class A
{
public:
double x = 0, y = 0;
A(const double x, const double y):
x(x), y(y)
{}
};
Now, I would need to set the members through the pointer, so I would think:
p[0].x += 1.0;
Since unique_ptr has the dereferencing [] operator, but that fails with:
error: no match for 'operator[]' (operand types are 'std::unique_ptr<std::array<A, 3ull> >' and 'int')
I reviewed similar questions, but it is unclear to me if what I want to do is possible. Is the [] operator for c-style declared arrays only?
Is the [] operator for c-style declared arrays only?
Yes, it's only supported for the array version, i.e. unique_ptr<T[]>, std::array is not counted.
You can use operator* instead, like
(*p)[0].x += 1.0;
How do you create type copies? For example, how do I create types Mass, Acceleration and Force which are not implicitly convertible to double(or any other numeric type), but otherwise have all the characteristics of a double. This would allow a compile-time input validity check for this function:
Force GetForceNeeded(Mass m, Acceleration a);
ensuring that GetForceNeeded can only be called with arguments of type Mass and Acceleration.
Of course, I could achieve this by manually creating a copy of the type:
class Force final
{
public:
//overload all operators
private:
double value;
};
but this is cumbersome. Is there a generic solution?
As many commentators have pointed out, one solution is to use BOOST_STRONG_TYPEDEF which provides all the features requested in the question. And here's example usage from their docs:
#include <boost/serialization/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(int, a)
void f(int x); // (1) function to handle simple integers
void f(a x); // (2) special function to handle integers of type a
int main(){
int x = 1;
a y;
y = x; // other operations permitted as a is converted as necessary
f(x); // chooses (1)
f(y); // chooses (2)
} typedef int a;
There is a proposal to add opaque typedefs to C++1y.
(I am leaving this answer as I can't find an exact dupe. Please flag if that isn't the case.)
Given the example code:
class Integer
{
int i_;
public:
Integer(int i) : i_(i) {}
const Integer operator+(const Integer &arg) const { return Integer(i_ + arg.i_); }
};
I started wondering whether operator+() should actually return a const Integer or not. Bruce Eckel in "Thinking in C++" provides examples for operator overloading for a similar case and seems to favor the const modifier on the return type. Should it be used and why?
On the other hand, let's try to use this class:
int main()
{
Integer a(1), b(2);
Integer c = a + b;
}
When creating c as a sum of a and b the compiler will most likely perform copy elision and Integer::operator+() will create its result in the spot occupied by c (see "Want speed? Pass by value") directly. But when the return type of Integer::operator+() is declared const, won't that force the compiler to perform copying since the target is non-const?
Returning an Integer const protects against things like:
(a + b) = c;
I've never found this to be too much of a problem, but forbidding it
does make the type behave more like the built-in types. It shouldn't
have any impact with regards to return value optimization.
If the class is extremely expensive to copy, and can be made to support
rvalue references effectively, you might want to avoid the const
because of these, but in practice, I suspect that such classes are rare
enough that you can afford to neglect them.
I want to overload the % operator in c++, in order to avoid editing a huge block of code by hand. I tried this:
static float operator %(const float& left, const float& right);
In my header, but it wont work because "nonmember operator requires a parameter with class or enum type".
I'm relatively new to C++, what am I supposed to do?
Operator overloads must have at least one of their arguments as a user-defined type. So you cannot do this.
What that means is that you cannot overload an operator when all the operands are non-class/enum types. i.e., you cannot override the behaviour of % when both sides are float (or int, or any other primitive type).
As has already been stated, you cannot define overloaded operators for intrinsic types.
However, if you are willing to take advantage of implicit type conversion you can achieve something close to what you require with a single cast to one of your floats on a wrapper type that implements an overloaded% operator.
class FloatWrapper
{
private:
float m_Float;
public:
FloatWrapper(float Value):
m_Float(Value)
{
}
friend float operator%(const FloatWrapper& lhs, const FloatWrapper& rhs)
{
//your logic here...
return (int)lhs.m_Float % (int)rhs.m_Float;
}
};
int main()
{
float Value1 = 15.0f;
float Value2 = 4.0f;
float fMod1 = (FloatWrapper)Value1 % Value2;
float fMod2 = Value1 % (FloatWrapper)Value2;
return 0;
}
class Test
{
public:
float operator%(float);
};
In C++ you need not to declare the operator as static, as opposed to C#. The argument can be of any type and the return value can also be. The first type would be the class itself.
Example:
Test test;
float x = test % 10.2f;