Can I replicate inheritance with overloading? - c++

Prelude: I have updated this question to address NicolBolas' suggestion. Please leave a constructive comment if you downvote, thank you.
I'm writing a function that takes a number (uint) or a flag that it's not a number. It then goes on to work with the given number or -1.
Here's the idea
struct Numeric {
virtual int to_int() const = 0;
};
struct NotANumber : Numeric {
int to_int () const {
return -1;
}
}
struct Number : Numeric {
const uint n;
Number (const uint n): n(n) {}
int to_int () const {
return n;
}
};
So then my function could be used as:
calculate_stuff(NotANumber());
calculate_stuff(Number(4));
My question is whether it's possible to move the to_int method outside of the classes, into the form of an overloaded function:
struct Numeric {};
struct NotANumber : Numeric {}
struct Number : Numeric {
const uint n;
Number (const uint n): n(n) {}
};
int Numeric_to_int (const NotANumber) {
return -1;
}
int Numeric_to_int (const Number n) {
return n.n;
}
This doesn't seem to work. Is it possible to fix this? Is the issue that overloading happens at compile time, whereas overriding is at runtime?
(I think I'm going to use std::optional and value_or for this specific problem, but I would still like to know the answer to my questions above)
Edit: sorry, I should've clarified what "doesn't work" means:
int calculate_stuff (const Numeric n) {
std::cout << Numeric_to_int(n) << std::endl;
return 0;
}
This doesn't compile: no matching function for call to ‘Numeric_to_int(const Numeric&)’

int calculate_stuff (const Numeric n)
How could it work? You passed in a base class. By value. The compiler cannot know what derived class it used to be. In fact, since you took the base class by value, the compiler knows that n is neither of the derived classes.
C++ isn't Java; if you pass something by value, you make a copy (or move to it). And if you passed one of the derived classes, that causes slicing; you only copy the base class data. The parameter is therefore exactly what it says: an object who's dynamic type is Numeric. Exactly and only that, not one of its derived classes.
Even if you took a const Numeric &n instead, that won't help. The compiler doesn't know what type it used to be. And you can't even use dynamic_cast to convert it back, since Numeric is not a polymorphic class.
A better way to handle this is to actually use a proper variant class (optional is effectively a specialized variant).

My question is whether it's possible to move the to_int method outside of the classes, into the form of an overloaded function.
Using overloaded non-member functions is a viable option only if you deal with the derived types at all times.
If you need the functionality through a reference or pointer to the base class type, then using overloaded non-member functions is not a viable option. In that case, a virtual member function is the right choice.

You can use a template class and an using declaration to do that:
template<int v>
struct Numeric {};
using NotANumber = Numeric<-1>;
template<int N>
constexpr int Numeric_to_int (Numeric<N>) {
return N;
}
int main() {
static_assert(Numeric_to_int(NotANumber{}) == -1, "!");
static_assert(Numeric_to_int(Numeric<42>{}) == 42, "!");
}
Also, consider the use of a std::integral_constant for the same purpose.
As an example:
template<int v>
using Numeric = std::integral_constant<int, v>;

Related

Declare member function only for specific template instantiation of class

Is it possible to declare a member function only for specific template instantiations of a class? This is why I want to do it:
// Polynomial<N> is a polynomial of degree N
template<int N>
class Polynomial {
public:
//... various shared methods e.g...
double eval(double x) const;
Polynomial<N-1> derivative() const;
Polynomial<N+1> integralFrom(double x0) const;
// ... various shared operators etc.
double zero() const; // only want Polynomial<1> to support this
// only want Polynomial<2> and Polynomial<1> to support the following
// because the solutions rapidly become too difficult to implement
std::vector<double> zeros() const;
std::vector<double> stationaryPoints() const { return derivative().zeros();}
private:
std::array<double,2> coeffs;
}
My current workaround is to just throw an exception from Polynomial<N>::zeros() for N>2 but it would have been nice to detect the problem at compile-time.
You can also use std::enable_if to SFINAE away the zero function.
template< int I >
class Poly {
public:
template<int Ib = I, typename = std::enable_if_t<Ib == 1> >
double zero()
{
return 42;
}
};
int main()
{
Poly< 10 > does_not_compile;
does_not_compile.zero();
//Poly< 1 > compile;
//compile.zero();
}
You can use CRTP to implement zeros and zero in a base class that knows about the derived one.
Then conditionally derive from one that has zeros and/or zero, or not.
template<class P>
struct zeros { /* todo */ };
template<class P>
struct zero:zeros<P> { /* todo */ };
struct nozero {};
template<int N>
struxt Polynomial:
std::conditional_t<
(N==1),
zero<Polynomial<N>>,
std::conditional_t<
(N==2),
zeros<Polynomial<N>>,
nozero
>
>
{
// body
};
Your solution is template specialization, in this case, full specialization.
However, I think you would need to think about your design. Generally, it is not a good idea to define different interfaces for different cases because you are not taking advantage of the abstraction.
For example, think about your stationaPoints() function. This functions should not be available for Polynomial<2> because the derivative is a Polynomial<1> which does not have the zeros() function. Your solution is to add the zeros function to the Polynomial<1> in order to homogenize the interface.
For your case, I guess you would like a solution which includes a N-1 c-vector inside the polynomial type with the zeros and a zero(i) function to get them. Something like this:
template <int N>
class Polynomial {
double _coefs[N+1];
double _zeros[N];
public:
double zero(size_t i) const { assert(i<N); return _zeros[i]; }
// ...
};
In this case, you could decide the strategy to calculate de zeros, depending on your application: constructor?, adding a boolean to know if it has been calculated then it is calculated in the first call to zero, etc...
I guess this solution could be more interesting for you because if you prefer a c-vector to store the coeficients, you wouldn't like the vector based interface of your zeros() function, would you?

Is there a default hash function for an unordered_set of a custom class?

I'm using a std::unordered_set for the first time and have a question about the hash function. As far as I understand, if you don't specify a hash function it will default to std::hash<Key>.
I have a mySet member in one of my classes:
typedef std::unordered_set<MyClass> USetType;
USetType mySet;
When I try to build, I get the following error:
error C2440: 'type cast' : cannot convert from 'const MyClass' to 'size_t'
Is it necessary to define a conversion function (to size_t) if you want to use unordered_set with a custom class? Is there any way to avoid writing your own hash function and just using the default?
If you don't specify your own hash functor as template argument, it will default to std::hash<MyClass>, which does not exist unless you define it.
Best define your own specialization of std::hash inside namespace std:
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
/* ..calculate hash value for t */
}
};
}
And make sure you include this code before the declaration of your hash. This way you can declare the hash simply as std::unordered_set<MyClass> with no need for further template arguments.
You didn't specify what MyClass looks like inside, but a typical situation is that your user-defined type simply consists of several simple-type members, for which a default hash function exists. In this case, you will probably want to combine the hash values for the individual types to a hash value for the entire combination. The Boost library provides a function called hash_combine for this purpose. Of course, there is no guarantee that it will work well in your particular case (it depends on the distribution of data values and the likelihood of collisions), but it provides a good and easy-to-use starting point.
Here is an example of how to use it, assuming MyClass consists of two string members:
#include <unordered_set>
#include <boost/functional/hash.hpp>
struct MyClass
{
std::string _s1;
std::string _s2;
};
namespace std {
template <>
struct hash<MyClass>
{
typedef MyClass argument_type;
typedef std::size_t result_type;
result_type operator()(const MyClass & t) const
{
std::size_t val { 0 };
boost::hash_combine(val,t._s1);
boost::hash_combine(val,t._s2);
return val;
}
};
}
int main()
{
std::unordered_set<MyClass> s;
/* ... */
return 0;
}
I'd like to expand on the answer given by jogojapan. As mentioned in a comment by CashCow on that answer, you also have to either overload the equality comparison operator (operator==) for MyClass or define a separate comparison function and provide it to the unordered_set. Otherwise, you will get another error message. For example, VS 2013 throws:
error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const MyClass' (or there is no acceptable conversion)
Moreover, you can use lambda expressions instead of defining the hash and comparison functions. If you don't want to use Boost, then you can also handcraft a hash function. I understand, that you want to use some default function, but a compiler doesn't know how to calculate a meaningful hash for a custom class. However, you can use std::hash for the members of your class. If you put everything together, then your code could be written as follows:
class MyClass {
public:
int i;
double d;
std::string s;
};
int main() {
auto hash = [](const MyClass& mc){
return (std::hash<int>()(mc.i) * 31 + std::hash<double>()(mc.d)) * 31 + std::hash<std::string>()(mc.s);
};
auto equal = [](const MyClass& mc1, const MyClass& mc2){
return mc1.i == mc2.i && mc1.d == mc2.d && mc1.s == mc2.s;
};
std::unordered_set<MyClass, decltype(hash), decltype(equal)> mySet(8, hash, equal);
return 0;
}
Code on Ideone

defining and calling conversion operator of a class

I'm reading the article at :
http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part-1
and i don't understand some point.
OKAY .How can "Convert" convert itself to any data type?
What does the float() and double() mean at the end of lines below ?? How can converting happen?Could you please explain it with details?
Convert<int>::operator<float> float();
Convert<int>::operator<double> double();
For those of you who wants related part of the article , I'm copy pasting it below and the related part to my question is at the end .
For sure, 'explicit template argument specification' with method template is also possible. Consider another example:
template<class T>
class Convert
{
T data;
public:
Convert(const T& tData = T()) : data(tData)
{ }
template<class C>
bool IsEqualTo( const C& other ) const
{
return data == other;
}
};
Which can be utilized as:
Convert<int> Data;
float Data2 = 1 ;
bool b = Data.IsEqualTo(Data2);
It instantiates Convert::IsEqualTo with float parameter. Explicit specification, as given below, would instantiate it with double:
bool b = Data.IsEqualTo<double>(Data2);
One of the astounding thing, with the help of templates, you can do it by defining conversion operator on top of template!
template<class T>
operator T() const
{
return data;
}
It would make possible to convert the Convert' class template instance into any type, whenever possible. Consider following usage example:
Convert<int> IntData(40);
float FloatData;
double DoubleData;
FloatData = IntData;
DoubleData = IntData;
Which would instantiate following two methods (fully qualified names):
Convert<int>::operator<float> float();
Convert<int>::operator<double> double();
On one hand it provides good flexibility, since without writing extra code, Convert can convert itself (the specific instantiation) to any data-type - whenever conversion is possible at compilation level. If conversion is not possible, like from double to string-type, it would raise an error.
A class type can have user-defined conversions. This allows you to convert an instance of the class into another type. For example, here we have a struct that when converted to an int always has the value 42:
struct A {
operator int() { return 42; }
};
This is a special function, operator int, that is called for conversion to an int. Now if we have an instance of A, a, we can easily convert it to an int:
A a;
int x = a; // x now has the value 42
In the article, they are showing how you can use templates to generate a conversion operator for any type. The function template is defined as:
template<class T>
operator T() const
{
return data;
}
Now, for whenever you try to convert your object into another type, a new version of that function will be generated, replacing T with the type that you're converting to. So if we do float f = a, the following function will generated:
operator float() const
{
return data;
}
This is a function that returns the internal data as a float.
The two lines in the article that are confusing you are just showing you which functions would be generated by the example:
Convert<int>::operator<float> float();
Convert<int>::operator<double> double();
The first is operator float that converts to a float. The second is operator double that converts to a double.

C++: Custom data type - typecasting and union issues

What I'm trying to do is create a new custom data type that behaves like all other primitive types. Specifically, this data type appears like a Fixed Point fraction.
I've created a class to represent this data type, called "class FixedPoint", and in it there are ways to typecast from "FixedPoint" to "int" or "double" or "unsigned int", etc. That is fine.
Now, what if I want to cast from "int" to "FixedPoint"? Originally my solution was to have a constructor:
FixedPoint(int i) { /* some conversion from 'int' to 'FixedPoint' in here */ }
This works...but you cannot put it into a union like so:
union {
FixedPoint p;
};
This will break, because "FixedPoint" does not have an implicit trivial constructor (we just defined a constructor, "FixedPoint(int i)").
To summarize, the whole issue is "we want to cast from some type T to type FixedPoint without explicitly defining a constructor so we can use our type FixedPoint in a union".
What I think the solution is but cannot find any evidence online:
Define an overloaded global typecast operator to cast from "int" to "FixedPoint".
Is there a way to do this without using class constructors? I'd like to be able to use this class in a union. What I've tried (in global scope):
operator (FixedPoint f, int a) { ... } //compiler complains about this is not a method or non-static.
And a little example to show unions don't like constructors (they like POD)
class bob
{
public:
bob(int a) { m_num = a; }
private:
int m_num;
};
void duck()
{
union
{
bob a;
};
}
This error seen in Visual Studio is:
error C2620: member 'duck::<unnamed-tag>::a' of union 'duck::<unnamed-tag>' has user-defined constructor or non-trivial default constructor
Any ideas?
Thanks
I am having a hard time at seeing what you would try to use this for. It seems smelly to have to constantly ensure that sizeof(FixedPoint) == sizeof(int) and, assuming that, there are other hidden gotchas, like endianness. Maybe I should back up a little bit here, unions only "convert" a value from one type to another in that it takes a chunk of memory and references it as a different type. i.e.
union BadConverter
{
int integer;
double fraction;
};
BadConverter.fraction = 100.0/33.0;
BadConverter.integer = ?;
I am pretty sure integer is not going to be 3, it is going to whatever the memory chunk of the double is that the integer bytes share with it.
Unions don't seem to be a very good fit for this sort of thing. I would think just defining a bunch of assignment operators from all the primitive types. i.e.
class FixedPoint
{
FixedPoint& operator=(int value);
FixedPoint& operator=(double value);
..etc..
//Maybe something like this?
template<typename T>
FixedPoint& operator=(const T& value)
{
value = boost::lexical_cast<int>(value);
return *this;
}
}
Custom conversion operators must be a member of the class that is being converted from. A non-trivial constructor is not required.
EDIT: I reworked the example to utilize a union since this is what you were asking about.
EDIT2: See below if you are trying to go the other way (construction) and don't want constructors.
#include <string>
#include <sstream>
using namespace std;
class FixedPoint
{
public:
operator std::string() const
{
stringstream ss;
ss << x_ << ", " << y_;
return ss.str();
}
int x_, y_;
};
union Items
{
FixedPoint point_;
int val_;
};
int main()
{
Items i;
i.point_.x_ = 42;
i.point_.y_ = 84;
string s = i.point_;
}
If you're trying to go the other way -- eg, from an int to FixedPoint in my example -- then the normal way to do this is indeed to use a conversion constructor. Given that you don't want a non-trivial constructor, you have to resort to a conversion function.
FixedPoint make_fixed_point(int x, int y)
{
FixedPoint ret;
ret.x_ = x;
ret.y_ = y;
return ret;
}
union Items
{
FixedPoint point_;
int val_;
};
int main()
{
Items i;
i.point_ = make_fixed_point(111,222);
}
Can't you just add a default constructor that'll allow it to be part of the union.
For example:
class bob
{
public:
bob(int a=0) { m_num = a; }
private:
int m_num;
};
void duck()
{
union
{
bob a;
};
}
By giving the a=0 default, it should be able to be put in a union. I didn't try it myself, though.

How can it be useful to overload the "function call" operator?

I recently discovered that in C++ you can overload the "function call" operator, in a strange way in which you have to write two pair of parenthesis to do so:
class A {
int n;
public:
void operator ()() const;
};
And then use it this way:
A a;
a();
When is this useful?
This can be used to create "functors", objects that act like functions:
class Multiplier {
public:
Multiplier(int m): multiplier(m) {}
int operator()(int x) { return multiplier * x; }
private:
int multiplier;
};
Multiplier m(5);
cout << m(4) << endl;
The above prints 20. The Wikipedia article linked above gives more substantial examples.
There's little more than a syntactic gain in using operator() until you start using templates. But when using templates you can treat real functions and functors (classes acting as functions) the same way.
class scaled_sine
{
explicit scaled_sine( float _m ) : m(_m) {}
float operator()(float x) const { return sin(m*x); }
float m;
};
template<typename T>
float evaluate_at( float x, const T& fn )
{
return fn(x);
}
evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
A algorithm implemented using a template doesn't care whether the thing being called is a function or a functor, it cares about the syntax. Either standard ones (e.g. for_each()) or your own. And functors can have state, and do all kinds of things when they are called. Functions can only have state with a static local variable, or global variables.
If you're making a class that encapsulates a function pointer, this might make the usage more obvious.
The compiler can also inline the functor and the function call. It cannot inline a function pointer, however. This way, using the function call operator can significantly improve performance when it is used for example with the standard C++ libary algorithms.
For example for implementing generators:
// generator
struct Generator {
int c = 0;
virtual int operator()() {
return c++;
}
};
int sum(int n) {
Generator g;
int res = 0;
for( int i = 0; i < n; i++ ) {
res += g();
}
return res;
}
I see potential to yet one exotic use:
Suppose you have object of unknown type and have to declare another variable of same type, like this:
auto c=decltype(a*b)(123);
When such pattern used extensively, decltype become very annoying.
This case can occur when using some smart type system that automatically invent type of result of functions and operators based on types of arguments.
Now, if each specialization of each type of that type system equipped with
magic definition of operator() like this:
template<????> class Num<???>{
//specific implementation here
constexpr auto operator()(auto...p){return Num(p...);}
}
decltype() no more needed, you can write simply:
auto c=(a*b)(123);
Because operator() of object redirects to constructor of its own type.