Say I have a class, that wraps some mathematic operation. Lets use a toy example
class Test
{
public:
Test( float f ) : mFloat( f ), mIsInt( false ) {}
fl
You can't "overload/add" operators for basic types, but you can for your type Type
. But this shall not be operator =
but operator >>
- like in istream
s.
class Test
{
public:
float mFloat;
int mInt;
bool mIsFloat;
Test& operator >> (float& v) { if (mIsFloat) v = mFloat; return *this; }
Test& operator >> (int& v) { if (!mIsFloat) v = mInt; return *this; }
};
Then you can:
int main() {
float v = 2;
Test t = { 1.0, 2, false };
t >> v; // no effect
t.mIsFloat = true;
t >> v; // now v is changed
}
Update
I want to do something like:
updateTime = config["system.updateTime"];
Then with my proposal, you cam:
config["system.updateTime"] >> updateTime;
You already have one implicit conversion from float
to Test
, in the form of the convert constructor
class Test
{
public:
/* ... */
Test( float f ) : mFloat( f ) /*...*/ {}
};
Which will support conversions such as:
Test t(0.5f);
You will likely also want a copy-assignement operator in order to make further implicit conversions from float
to Test
possible:
class Test
{
public:
Test& operator=(float f) { mFloat = f; return *this; }
};
t = 0.75; // This is possible now
In order to support implicit conversion from Test
to float
you don't use operator=
, but a custom cast operator, declared & implemented thusly:
class Test
{
public:
/* ... */
operator float () const { return mFloat; }
};
This makes implicit conversions posslible, such as:
float f = t;
As an aside, you have another implicit conversion happening here you may not even be aware of. In this code:
Test t( 0.5 );
The literal value 0.5
isn't a float
, but a double
. In order to call the convert constructor this value must be converted to float
, which may result in loss of precision. In order to specify a float
literal, use the f
suffix:
Test t( 0.5f );
Using template specialization:
class Config {
template<typename T>
void setValue(const std::string& index, T& value); //sets the value if available
};
template<float>
void Config::setValue(const std::string& index, float& value){...} //only sets float values
template<int>
void Config::setValue(const std::string& index, int& value){...} //only sets int values;
Based on your example, what you really want is an implicit conversion operator:
class Test
{
// ...
public:
operator float() const;
};
inline Test::operator float() const
{
return mIsFloat ? mFloat : mInt;
}
If you want to conditionally do the assignment, then you need to take another approach. A named method would probably be the best option, all things considered... something like this:
class Test
{
public:
bool try_assign(float & f) const;
};
inline bool Test::try_assign(float & f) const
{
if (mIsFloat) {
f = mFloat;
}
return mIsFloat;
}
Whatever you do, be careful that the syntactic sugar you introduce doesn't result in unreadable code.