Wrapper for numeric values - c++

I am trying to write a C++ program which wraps numeric values, I am doing this by writing a super class which will handle two simple functions, and an operator overloading function. This is the code I have so far:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template <class T>
class Number {
protected:
T number;
public:
Number(T num) {
number = num;
}
string mytype() {
return typeid(number).name();
}
string what_am_i() {
ostringstream oss;
oss << "I am " << Number<T>::mytype() << " and my value is " << number;
return oss.str();
}
Number operator+ (Number an) {
Number brandNew = NULL;
brandNew.number = number + an.number;
return brandNew;
}
};
class MyInt : public Number<int> {
public:
MyInt() : Number<int>(0) {};
MyInt(int num) : Number<int>(num) {}
MyInt(const Number<int> &x) : Number<int>(x) {}
};
class MyFloat : public Number<float> {
public:
MyFloat() : Number<float>(0){};
MyFloat(float num) : Number(num){}
MyFloat(const Number<float> &x) : Number<float>(x) {}
};
class MyDouble : public Number<double> {
public:
MyDouble() : Number<double>(0){};
MyDouble(double num) : Number(num){}
MyDouble(const Number<double> &x) : Number<double>(x) {}
};
In the main function I would like to do something like :
void main() {
MyInt two = 2;
MyFloat flo = 5.0f;
MyDouble md3 = flo + two;
}
And wish for md3 to be 15.00000, up to now an addition of two objects from the same type works great but when I am trying to add a MyInt and MyFloat the compiler doesn't like it. Does anyone have an idea how could I implement this?

You have to add the type operator for your template class:
operator T()
{
return number;
}
This is the complate code that I tested and work:
template <class T>
class Number {
protected:
T number;
public:
Number(T num) {
number = num;
}
string mytype() {
return typeid(number).name();
}
string what_am_i() {
ostringstream oss;
oss << "I am " << Number<T>::mytype() << " and my value is " << number;
return oss.str();
}
Number operator+ (Number an) {
Number brandNew = NULL;
brandNew.number = number + an.number;
return brandNew;
}
operator T()
{
return number;
}
};
I try to explain better why it works. When you make overloading of the plus operator, you want to do something like: left_value + right_value, where right_value is the "an" argument of the plus operator.
Now to get the right value of your object "an", you have to overloading the "type operator", if you don't make overloading of this operator inside your Number class it can not be read as a right value. The following example is for the operator=(), but is valid also for operator+():
template<typename T>
class Number
{
T value;
public:
T operator=(T arg) // Assignment, your class is seen as left operand
{
value = arg;
}
operator T() // Getting, your class is seen as right operand
{
return value;
}
}
Number<int> A; // define a new class Number as int
Number<double> B; // define a new class Number as double
A = B; // is same to A.operator=( B.double() );
to assign A as left value is called the operator "operator=()" of the class Number, while to get B as right value is called the "operator T()" of the class Number
Now this is translated as:
// instance of the operator = of the class Number<int>
int operator=(int arg)
{
}
// instance of the Operator T of the class Number<double>
operator double()
{
}
this traslation emulates the follwoing semantic for A and B object:
int A;
double B;
A = B;
Ciao
Angelo

You may specify the result of a binary operation and use a freestanding operator:
#include <iostream>
#include <typeinfo>
template <class T>
class Number {
template <typename>
friend class Number;
protected:
T number;
public:
Number(const T& num)
: number(num)
{}
template <typename U>
Number(const Number<U>& num)
: number(num.number)
{}
// ...
const T& value() const { return number; }
};
typedef Number<int> MyInt;
typedef Number<float> MyFloat;
typedef Number<double> MyDouble;
template <typename A, typename B>
struct NumberResult;
template <typename X>
struct NumberResult<X, X> {
typedef X type;
};
template <> struct NumberResult<int, float> { typedef float type; };
template <> struct NumberResult<float, int> { typedef float type; };
// ...
template <typename A, typename B>
inline Number<typename NumberResult<A, B>::type>
operator + (const Number<A>& a, const Number<B>& b) {
return Number<typename NumberResult<A, B>::type>(a.value() + b.value());
}
Note: Please avoid using namespace std; in a header.

Related

How to get n-th attribute of class in C++

With a normal class. For example:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
}
We can do:
A x;
x.a = 1;
x.b = "hello";
But now I don't want to do like above. I want to access n_index-th attribute of object. For example pseudo like x.get<2>() (or x.set<2>(...)) like x.b.
How can do that? Have any template for that.
Beside if I want code like that
int number = 2;
x.get<number>()
Any problem with constexpr?
I think the closest you can get is using boost::fusion.
An example would be
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/int.hpp>
#include <iostream>
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
BOOST_FUSION_ADAPT_STRUCT(A,
(int, a)
(std::string, b)
)
using namespace boost::fusion;
int main()
{
A x;
x.a = 1;
x.b = "hello";
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
at<boost::mpl::int_<0>>(x) = 5;
at<boost::mpl::int_<1>>(x) = std::string("World");
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
}
If you want to set several values at the same time when you create the object, you could use a multi-parameter constructor. For example, let's imagine you have this:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
You could add a constructor that sets a and b:
class A {
public:
int a;
std::string b;
A() {}
A(int a, std::string b) {
this->a = a;
this->b = b;
}
~A() {}
};
That way, you can create your object and set a and b with :
A a = A(1, "hello");
There is no ready-made way of setting the n-th attribute of your object. You could make one, but I would very, very highly recommend that you don't. Like I said above, if you reorder your attributes, then you will have to rework everything.
If you really, really want to make your life very, very, very much harder, a very ugly and error-prone way of doing this would be like :
template<class T>
void A::setNth(int nth, const T& value) {
switch (nth) {
case 1: a = value; break;
case 2: b = value; break;
// You should #include <stdexcept> to use runtime_error, or you could handle the exception in some other way.
default: throw std::runtime_error("A::setNthAttribute : Value of nth is out of bounds.");
}
}
For the getter:
template<class T>
void A::getNth(int nth, T& valueOut) {
switch (nth) {
case 1: valueOut = a; break;
case 2: valueOut = b; break;
default: throw std::runtime_error("A::getNthAttribute : Value of nth is out of bounds.");
}
}
You would use these methods like this:
A a;
a.setNth(1, 2); // put 2 into a
int i;
a.getNth(1, i); // put a into i
Just writing this code send shivers down my spine. Please, never write what I just wrote. Chuck Norris will kill yoU agfh
86sd asdsa dDASD8!4.
What you are considering is in fact possible, but a bit of a headache. I would approach it by creating a template getter and setter for every member that one can set or get, and then having a template method that takes an int and sets or gets the appropriate property. The getters/setters would have to be specialized for the correct type, and throw an error for other types. This method would have to use a switch to return the right member:
class bar {
private:
int a;
std::string b;
template<T>
T getA() {
// error
}
template<T>
T getB() {
// error
}
template<T>
void setA(const T& A) {
// error
}
template<T>
void setB(const T& B) {
// error
}
template <> std::string getB(); // specialization
template <> int getA();
template <> void setB(const std::string&);
template <> void setA(int);
public:
template<T>
T get(int what) {
switch(what) {
case 1:
return getA();
case 2:
return getB();
default:
// handle error here
break;
}
}
template<T>
void set(int what, const T& t) {
switch(what) {
case 1:
return setA<T>(t);
case 2:
return setB<T>(t);
default:
// handle error here
break;
}
}
};
bar b;
b.set<std::string>(2, "foo");
auto str = b.get<std::string>(2);
Here's an elaborate way to accomplish what you want.
#include <iostream>
#include <string>
// A namespace explicitly defined for class A.
namespace A_NS
{
// A template for members of A.
template <int> struct Member;
// Specialization for the first member.
template <> struct Member<1>
{
using type = int;
type var;
};
// Specialization for the second member.
template <> struct Member<2>
{
using type = std::string;
type var;
};
}
class A {
public:
A() {}
~A() {}
template <int N> typename A_NS::Member<N>::type get() const
{
return static_cast<A_NS::Member<N> const&>(members).var;
}
template <int N> void set(typename A_NS::Member<N>::type const& in)
{
static_cast<A_NS::Member<N>&>(members).var = in;
}
private:
// Define a type for the member variables.
struct Members : A_NS::Member<1>, A_NS::Member<2> {};
// The member variables.
Members members;
};
int main()
{
A a;
a.set<1>(10);
a.set<2>("test");
std::cout << a.get<1>() << ", " << a.get<2>() << std::endl;
}
Output:
10, test

Is there a way to have a public member, unmodifiable from outside the class, without accessor wrapper function?

As far as I know, this seems to be impossible in a straightforward way. Making the member const makes it const for everyone. I would like to have a read-only property, but would like to avoid the typical "getter". I'd like const public, mutable private. Is this at all possible in C++?
Currently all I can think of is some trickery with templates and friend. I'm investigating this now.
Might seem like a stupid question, but I have been surprised by answers here before.
A possible solution can be based on an inner class of which the outer one is a friend, like the following one:
struct S {
template<typename T>
class Prop {
friend struct S;
T t;
void operator=(T val) { t = val; }
public:
operator const T &() const { return t; }
};
void f() {
prop = 42;
}
Prop<int> prop;
};
int main() {
S s;
int i = s.prop;
//s.prop = 0;
s.f();
return i, 0;
}
As shown in the example, the class S can modify the property from within its member functions (see S::f). On the other side, the property cannot be modified in any other way but still read by means of the given operator that returns a const reference to the actual variable.
There seems to be another, more obvious solution: use a public const reference member, pointing to the private, mutable, member. live code here.
#include <iostream>
struct S {
private:
int member;
public:
const int& prop;
S() : member{42}, prop{member} {}
S(const S& s) : member{s.member}, prop{member} {}
S(S&& s) : member(s.member), prop{member} {}
S& operator=(const S& s) { member = s.member; return *this; }
S& operator=(S&& s) { member = s.member; return *this; }
void f() { member = 32; }
};
int main() {
using namespace std;
S s;
int i = s.prop;
cout << i << endl;
cout << s.prop << endl;
S s2{s};
// s.prop = 32; // ERROR: does not compile
s.f();
cout << s.prop << endl;
cout << s2.prop << endl;
s2.f();
S s3 = move(s2);
cout << s3.prop << endl;
S s4;
cout << s4.prop << endl;
s4 = s3;
cout << s4.prop << endl;
s4 = S{};
cout << s4.prop << endl;
}
I like #skypjack's answer, but would have written it somehow like this:
#include <iostream>
template <class Parent, class Value> class ROMember {
friend Parent;
Value v_;
inline ROMember(Value const &v) : v_{v} {}
inline ROMember(Value &&v) : v_{std::move(v)} {}
inline Value &operator=(Value const &v) {
v_ = v;
return v_;
}
inline Value &operator=(Value &&v) {
v_ = std::move(v);
return v_;
}
inline operator Value& () & {
return v_;
}
inline operator Value const & () const & {
return v_;
}
inline operator Value&& () && {
return std::move(v_);
}
public:
inline Value const &operator()() const { return v_; }
};
class S {
template <class T> using member_t = ROMember<S, T>;
public:
member_t<int> val = 0;
void f() { val = 1; }
};
int main() {
S s;
std::cout << s.val() << "\n";
s.f();
std::cout << s.val() << "\n";
return 0;
}
Some enable_ifs are missing to really be generic to the core, but the spirit is to make it re-usable and to keep the calls looking like getters.
This is indeed a trickery with friend.
You can use curiously recurring template pattern and friend the super class from within a property class like so:
#include <utility>
#include <cassert>
template<typename Super, typename T>
class property {
friend Super;
protected:
T& operator=(const T& val)
{ value = val; return value; }
T& operator=(T&& val)
{ value = val; return value; }
operator T && () &&
{ return std::move(value); }
public:
operator T const& () const&
{ return value; }
private:
T value;
};
struct wrap {
wrap() {
// Assign OK
prop1 = 5; // This is legal since we are friends
prop2 = 10;
prop3 = 15;
// Move OK
prop2 = std::move(prop1);
assert(prop1 == 5 && prop2 == 5);
// Swap OK
std::swap(prop2, prop3);
assert(prop2 == 15 && prop3 == 5);
}
property<wrap, int> prop1;
property<wrap, int> prop2;
property<wrap, int> prop3;
};
int foo() {
wrap w{};
w.prop1 = 5; // This is illegal since operator= is protected
return w.prop1; // But this is perfectly legal
}

Constructor Overloading Ambiguity When Trying to Support Literals

Code
#include <iostream>
template <typename Type>
class MyContainer
{
private:
Type contained;
public:
MyContainer<Type>(Type & a): contained(a) { std::cout << "&\n"; }
MyContainer<Type>(Type a): contained(a) { std::cout << "_\n"; }
};
class Epidemic
{
private:
int criticality;
public:
Epidemic(int c): criticality(c);
};
int main()
{
// using objects //
Epidemic ignorance(10);
MyContainer<Epidemic> testtube(ignorance); // should print "&"; error instead
// using primitive //
double irrationalnumber = 3.1415;
MyContainer<double> blasphemousnumber(irrationalnumber); // should print "&"; error instead
// using literal //
MyContainer<double> digits(123456789.0); // prints "_"
}
Description
MyContainer<Type>(Type & a) is meant for most everything. However, it won't work with literals (e.g. 1.732). That's why I added a MyContainer<Type>(Type a). However, by adding this, I end up with an ambiguity because non-literals can use either constructor.
Question
Is there a way to satisfy all parameters (both literal and non-literal) given to a constructor?
Just change from the value type parameter to a const reference:
template <typename Type>
class MyContainer
{
private:
Type contained;
public:
MyContainer<Type>(Type & a): contained(a) { std::cout << "&\n"; }
MyContainer<Type>(const Type& a): contained(a) { std::cout << "_\n"; }
// ^^^^^ ^
};

Adding a template typename to two template classes

I have learned this code like inheritance by using template technique on C++. This code works.
#include <iostream>
using namespace std;
template < typename T >
class Base {
public:
explicit Base(const T& policy = T()) : m_policy(policy) {}
void doSomething()
{
m_policy.doA();
m_policy.doB();
}
private:
T m_policy;
};
class Implemented {
public:
void doA() { cout << "A"; };
void doB() { cout << "B"; };
};
int main() {
Base<Implemented> x;
x.doSomething();
return 0;
}
However, is it possible to add arguments with new typename S in doA and doB? For example, this code doesn't work by type/value mismatch errors.
#include <iostream>
using namespace std;
template < typename T, typename S >
class Base {
public:
explicit Base(const T& policy = T()) : m_policy(policy) {}
void doSomething()
{
m_policy.doA(m_s);
m_policy.doB(m_s);
}
private:
T m_policy;
S m_s;
};
template < typename S >
class Implemented {
public:
void doA(S& s) { cout << "A" << s; };
void doB(S& s) { cout << "B" << s; };
};
int main() {
Base<Implemented, int> x;
x.doSomething();
return 0;
}
I guess I must let both class Base and Implemented know about an actual type of S at main(). How can I fix this issue? Thank you for your help in advance.
In this line:
Base<Implemented, int> x;
Implemented is no longer a type, now you made it a template. But Base still expects a type - so give it one:
Base<Implemented<int>, int> x;
When Implemented was a class, you used a template parameter T. Now that Implmented is a template class, you need to use a so called template template parameter, like so:
#include <iostream>
using namespace std;
template < template <class TS> class T, typename S >
class Base {
public:
explicit Base(const T<S>& policy = T<S>()) : m_policy(policy) {}
void doSomething()
{
m_policy.doA(m_s);
m_policy.doB(m_s);
}
private:
T<S> m_policy;
S m_s;
};
template < typename S >
class Implemented {
public:
void doA(S& s) { cout << "A" << s; };
void doB(S& s) { cout << "B" << s; };
};
int main() {
Base<Implemented, int> x;
x.doSomething();
return 0;
}

Overloading an operator through friend function and returning a type different from the rhs parameters

I am attaching the code here and explaining the problem below:
Here is the class Bitop:
#ifndef _Bitop_H
#define _Bitop_H
# include <iostream>
double num2fxp(double v, int bits=9, int intbits=5){
return -0.5;
}
template<int bits = 8, int intbits = 6>
class Bitop
{
template<int rhsbits, int rhsintbits> friend class Bitop;
private:
double value; // data value
public:
Bitop(const double& v=0):
value(num2fxp(v, bits, intbits))
{}
template<int rhsbits, int rhsintbits>
const Bitop<bits, intbits>& operator = (const Bitop<rhsbits, rhsintbits>& v){
value = num2fxp(v.value, bits, intbits);
return *this;
}
template<int rhsbits, int rhsintbits>
Bitop<bits, intbits>& operator += (const Bitop<rhsbits, rhsintbits>& v) {
value = num2fxp(value+v.value, bits, intbits);
return *this;
}
template<int lhsbits, int lhsintbits, int rhsbits, int rhsintbits>
friend Bitop<lhsintbits+rhsintbits+2, lhsintbits+rhsintbits+1> operator + (const Bitop<lhsbits, lhsintbits>& x, const Bitop<rhsbits, rhsintbits>& y){
return Bitop<lhsintbits+rhsintbits+2, lhsintbits+rhsintbits+1> (num2fxp(x.value+y.value));
}
friend std::ostream& operator<< (std::ostream & out, const Bitop& y){return out << y.value ;}
void Print(){
std::cout << value<< "<"
<< bits << ","
<< intbits << ">";
}
};
#endif
And the Test function:
# include <iostream>
# include "Bitop.H"
using namespace std;
int main (int argc, char** argv) {
Bitop<4,1> a = 0.8;
Bitop<5,2> b(3.57);
Bitop<7,3> c;
c = b;
cout << "See all attributes of c \n";
c.Print();cout << "\n";
c = 7.86;
cout << "reassign c to a new value\n";
c.Print();cout << "\n";
cout << "set b = c \n";
b = c;
b.Print();cout<<"\n";
cout << "set b+=a \n";
b += a;
b.Print();cout<<"\n";
cout << "set b=c+a \n";
b = c+a;
b.Print();cout<<"\n";
return 0;
}
I have a templated class Bitop. I want to overload "+" to add 2 objects with different template parameters and return a third object with parameters different from the rhs and lhs objects, i.e. I want to do the following:
Bitop<5,3> + Bitop<4,2> should return Bitop<10,6>. I declared Bitop to be a friend class of itself so I can access the private members of rhs and lhs objects. But I am getting compilation error (due to redefinition) regardless of whether I call the "+" function.
I am not clear about what I am doing wrong here. Any help is appreciated.
Please note that I left a couple of functions and function calls in the code to ensure that other overloads such as = and += work correctly.
Here's a simplified example that shows the same problem:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a>, X<b>) { }
};
int main()
{
X<1> x1;
X<4> x2; // error: redefinition of foo
}
Every time a new specialization of X gets instantiated, the definition of foo is inserted in the scope sorounding the template class X. I hope it's clear where the error is coming from.
Things would be different if the declaration depended on template parameter of the class, like:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a+i>, X<b+i>) { } // different definiton
// for each specialization of X
};
The solution is to define the friend function outside of class:
template<int i>
struct X {
template<int a, int b>
friend void foo(X<a>, X<b>);
};
template<int a, int b>
void foo(X<a>, X<b>) { }
int main()
{
X<1> x1;
X<4> x2;
}
You don't really need to define operator+ as friend:
template<int I>
class A
{
double X;
template<int> friend class A;
public:
A(A const&) = default;
A(double x)
: X(x) {}
template<int J>
A(A<J> const&a)
: X(a.X) {}
template<int J>
A<I+J> operator+ (A<J> const&a)
{ return A<I+J>(X+a.X); }
};
int main()
{
A<0> a0(3);
A<1> a1(4);
auto ax = a0+a1;
}
Moreover, the result returned by operator+(a,b) should really be identical to that obtained by operator=(a) followed by operator+=(b).