Jump to content

[C++11] Help With Templates

Hey guys. To learn templates, I've been working on emulating the Java and C# object-for-basic-types framework in C++ templates. The end goal is to be able to use them interchangeably with the primitive data type it encapsulates, as well as extend them using things like toString() etc. This is where I am so far:

 

#ifndef TEMPLATEOBJECT_H
#define TEMPLATEOBJECT_H

#include <string>
#include <sstream>
#include <cassert>
#include <initializer_list>

#if __cplusplus <= 199711L
  #error This library needs at least a C++11 compliant compiler
#endif

template<typename T>
class Object
{
public:
    virtual std::string toString() const = 0;
    virtual T value() const = 0;
    virtual int getHashCode() const = 0;
};

template <typename T, typename = std::enable_if<std::is_integral<T>::value>>
class TemplateObject : public Object<T>
{
public:
    explicit TemplateObject(const T &value) : _value{value} {}
    explicit TemplateObject(T value) : _value{value} {}
    explicit TemplateObject(std::initializer_list<T> ini) {
        assert(ini.size() == 1);
        _value = *(ini.begin());
    }
    //TemplateObject<T>& operator=(const TemplateObject<T>& other) { return *this; } //Copy constructor
    //TemplateObject<T>& operator=(TemplateObject<T>&& other) { return *this; } //Move constructor
    TemplateObject<T> &operator=(T value) {
        this->_value = value;
        return &this;
    }

    TemplateObject<T>& operator++() {
        this->_value = (this->_value+1);
        return *this;
    }

    TemplateObject<T>& operator--() {
        this->_value = (this->_value-1);
        return *this;
    }

    TemplateObject<T> operator++(int) {
        TemplateObject previous{*this};
        operator++();
        return previous;
    }

    TemplateObject<T> operator--(int) {
        TemplateObject previous{*this};
        operator--();
        return previous;
    }

    /*binary math operators*/
    friend inline TemplateObject<T> operator+(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs += rhs.value()); }
    friend inline TemplateObject<T> operator-(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs -= rhs.value()); }
    friend inline TemplateObject<T> operator*(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs *= rhs.value()); }
    friend inline TemplateObject<T> operator/(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs /= rhs.value()); }
    friend inline TemplateObject<T> operator%(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs %= rhs.value()); }
    friend inline TemplateObject<T> operator^(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs ^= rhs.value()); }
    friend inline TemplateObject<T> operator&(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs &= rhs.value()); }
    friend inline TemplateObject<T> operator|(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs |= rhs.value()); }

    friend inline TemplateObject<T> operator+(TemplateObject<T> lhs, const T &rhs) { return (lhs += rhs); }
    friend inline TemplateObject<T> operator-(TemplateObject<T> lhs, const T &rhs) { return (lhs -= rhs); }
    friend inline TemplateObject<T> operator*(TemplateObject<T> lhs, const T &rhs) { return (lhs *= rhs); }
    friend inline TemplateObject<T> operator/(TemplateObject<T> lhs, const T &rhs) { return (lhs /= rhs); }
    friend inline TemplateObject<T> operator%(TemplateObject<T> lhs, const T &rhs) { return (lhs %= rhs); }
    friend inline TemplateObject<T> operator^(TemplateObject<T> lhs, const T &rhs) { return (lhs ^= rhs); }
    friend inline TemplateObject<T> operator&(TemplateObject<T> lhs, const T &rhs) { return (lhs &= rhs); }
    friend inline TemplateObject<T> operator|(TemplateObject<T> lhs, const T &rhs) { return (lhs |= rhs); }

    friend inline T operator+(T &lhs, const TemplateObject<T> &rhs) { return (lhs += rhs.value()); }
    friend inline T operator-(T &lhs, const TemplateObject<T> &rhs) { return (lhs -= rhs.value()); }
    friend inline T operator*(T &lhs, const TemplateObject<T> &rhs) { return (lhs *= rhs.value()); }
    friend inline T operator/(T &lhs, const TemplateObject<T> &rhs) { return (lhs /= rhs.value()); }
    friend inline T operator%(T &lhs, const TemplateObject<T> &rhs) { return (lhs %= rhs.value()); }
    friend inline T operator^(T &lhs, const TemplateObject<T> &rhs) { return (lhs ^= rhs.value()); }
    friend inline T operator&(T &lhs, const TemplateObject<T> &rhs) { return (lhs &= rhs.value()); }
    friend inline T operator|(T &lhs, const TemplateObject<T> &rhs) { return (lhs |= rhs.value()); }

    friend inline std::ostream& operator<<(std::ostream& lhs, const TemplateObject<T>& rhs) { return (lhs << rhs.value()); }
    friend inline std::istream& operator>>(std::istream& lhs, const TemplateObject<T>& rhs) { return (lhs >> rhs.value()); }

    /*Equality/Relational Operators*/
    friend inline bool operator<(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs.value() < rhs.value()); }
    friend inline bool operator>(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs.value() > rhs.value()); }
    friend inline bool operator<=(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs.value() <= rhs.value()); }
    friend inline bool operator>=(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return  (lhs.value() >= rhs.value()); }
    friend inline bool operator==(TemplateObject<T> lhs, const TemplateObject<T>& rhs) { return (lhs.value() == rhs.value()); }

    friend inline bool operator<(const T &lhs, const TemplateObject<T> &rhs) { return (lhs < rhs.value()); }
    friend inline bool operator>(const T &lhs, const TemplateObject<T> &rhs) { return (lhs > rhs.value()); }
    friend inline bool operator<=(const T &lhs, const TemplateObject<T> &rhs) { return (lhs <= rhs.value()); }
    friend inline bool operator>=(const T &lhs, const TemplateObject<T> &rhs) { return  (lhs >= rhs.value()); }
    friend inline bool operator==(const T &lhs, const TemplateObject<T> &rhs) { return (lhs == rhs.value()); }

    friend inline bool operator<(const TemplateObject<T> &lhs, const T &rhs) { return (lhs.value() < rhs); }
    friend inline bool operator>(const TemplateObject<T> &lhs, const T &rhs) { return (lhs.value() > rhs); }
    friend inline bool operator<=(const TemplateObject<T> &lhs, const T &rhs) { return (lhs.value() <= rhs); }
    friend inline bool operator>=(const TemplateObject<T> &lhs, const T &rhs) { return  (lhs.value() >= rhs); }
    friend inline bool operator==(const TemplateObject<T> &lhs, const T &rhs) { return (lhs.value() == rhs); }

    /*Compound assignment operators*/
    TemplateObject<T> &operator+=(const TemplateObject<T> &rhs) {
        this->_value = this->_value + rhs.value();
        return *this;
    }

    TemplateObject<T> &operator-=(const TemplateObject<T> &rhs) {
        this->_value = this->_value - rhs.value();
        return *this;
    }
    TemplateObject<T> &operator*=(const TemplateObject<T> &rhs) {
        this->_value = this->_value * rhs.value();
        return *this;
    }
    TemplateObject<T> &operator/=(const TemplateObject<T> &rhs) {
        this->_value = this->_value / rhs.value();
        return *this;
    }
    TemplateObject<T> &operator%=(const TemplateObject<T> &rhs) {
        this->_value = this->_value % rhs.value();
        return *this;
    }
    TemplateObject<T> &operator^=(const TemplateObject<T> &rhs) {
        this->_value = this->_value ^ rhs.value();
        return *this;
    }
    TemplateObject<T> &operator&=(const TemplateObject<T> &rhs) {
        this->_value = this->_value & rhs.value();
        return *this;
    }
    TemplateObject<T> &operator|=(const TemplateObject<T> &rhs) {
        this->_value = this->_value | rhs.value();
        return *this;
    }

    TemplateObject<T> &operator+=(const T &rhs) {
        this->_value = this->_value + rhs;
        return *this;
    }

    TemplateObject<T> &operator-=(const T &rhs) {
        this->_value = this->_value - rhs;
        return *this;
    }
    TemplateObject<T> &operator*=(const T &rhs) {
        this->_value = this->_value * rhs;
        return *this;
    }
    TemplateObject<T> &operator/=(const T &rhs) {
        this->_value = this->_value / rhs;
        return *this;
    }
    TemplateObject<T> &operator%=(const T &rhs) {
        this->_value = this->_value % rhs;
        return *this;
    }
    TemplateObject<T> &operator^=(const T &rhs) {
        this->_value = this->_value ^ rhs;
        return *this;
    }
    TemplateObject<T> &operator&=(const T &rhs) {
        this->_value = this->_value & rhs;
        return *this;
    }
    TemplateObject<T> &operator|=(const T &rhs) {
        this->_value = this->_value | rhs;
        return *this;
    }

    /*toString using stringstream*/
    std::string toString() const {
        std::string returnString;
        std::stringstream transfer;
        transfer << this->_value;
        transfer >> returnString;
        return returnString;
    }

    T value() const { return _value; }
    operator T() { return this->_value; }
    void setValue(T value) { this->_value = value; }
    void setValue(const T &value) { this->_value = value; }
    void setValue(TemplateObject<T> object) { this->_value = object.value(); }
    void setValue(const TemplateObject<T> &object) { this->_value = object.value(); }
    int getHashCode() const { return (this->_value); }
protected:
        T _value;
};


class Integer : public TemplateObject<int>
{
    using TemplateObject<int>::TemplateObject; //constructor inheritance since c++11
public:
    Integer(int value) : TemplateObject<int>({value}) {}
    operator int() { return this->_value; }
};

class Long : public TemplateObject<long>
{
    using TemplateObject<long>::TemplateObject; //constructor inheritance since c++11
public:
    Long(long value) : TemplateObject<long>({value}) {}
    operator long() { return this->_value; }
};

class Boolean : public TemplateObject<bool>
{
    using TemplateObject<bool>::TemplateObject; //constructor inheritance since c++11
public:
    Boolean(bool value) : TemplateObject<bool>({value}) {}
    operator bool() { return this->_value; }
};

class Double : public TemplateObject<double>
{
    using TemplateObject<double>::TemplateObject; //constructor inheritance since c++11
public:
    Double(double value) : TemplateObject<double>({value}) {}
    operator double() { return this->_value; }
};

class Float : public TemplateObject<float>
{
    using TemplateObject<float>::TemplateObject; //constructor inheritance since c++11
public:
    Float(float value) : TemplateObject<float>({value}) {}
    operator float() { return this->_value; }
};

class Character : public TemplateObject<char>
{
    using TemplateObject<char>::TemplateObject; //constructor inheritance since c++11
public:
    Character(char value) : TemplateObject<char>({value}) {}
    operator char() { return this->_value; }
};

#endif //TEMPLATEOBJECT_H

 

 

I've done "unit testing" on the Integer class and everything seems to work okay. I guess my main request is this: Do you see anything blatantly wrong with this code? Do you have any suggestions for how to make it better?

 

Thanks!

Link to comment
Share on other sites

Link to post
Share on other sites

What would be the use for this if i may ask? It seems to me not only does it add an extra layer (of inefficiency) over data types that already support these operations, it also opens a can of worms for protecting against sensless combinations. For example "TemplateObject<PrinterDevice>::operator++" ?

Link to comment
Share on other sites

Link to post
Share on other sites

What is the point?

Instead of a "tostring()" function overload the output stream operator:

http://www.cprogramming.com/tutorial/c++-iostreams.html

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to comment
Share on other sites

Link to post
Share on other sites

18 minutes ago, mathijs727 said:

What is the point?

 

 

33 minutes ago, Unimportant said:

What would be the use for this if i may ask?

 

16 hours ago, Pinguinsan said:

To learn templates

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×