Please see the following code:
// templateClassTemplate.cpp
#include <iostream>
class Account{
public:
explicit Account(double amount=0.0): balance(amount){}
void deposit(double amount){
balance+= amount;
}
void withdraw(double amount){
balance-= amount;
}
double getBalance() const{
return balance;
}
private:
double balance;
};
template <typename T, int N>
class Array{
public:
Array()= default;
int getSize() const;
private:
T elem[N];
};
template <typename T, int N>
int Array<T,N>::getSize() const {
return N;
}
int main(){
std::cout << std::endl;
Array<double,10> doubleArray;
std::cout << "doubleArray.getSize(): " << doubleArray.getSize() << std::endl;
Array<Account,1000> accountArray;
std::cout << "accountArray.getSize(): " << accountArray.getSize() << std::endl;
std::cout << std::endl;
}
This code is taken from a learning course on template initialisation.
I have two questions:
How is the object Array<double,10> doubleArray initialized since it is using a default constructor that takes no arguments?
How is the object Array<Account,1000> accountArray initialized?
The template is instantiated by replacing the type T in the template with the type given as the first argument, and the integer N with the value of the second argument.
The same thing happens when instantiating the definition of getSize.
That is, Array<double,10> doubleArray; works exactly the same as
class DoubleArray10{
public:
DoubleArray10()= default;
int getSize() const;
private:
double elem[10];
};
int DoubleArray10::getSize() const { return 10; }
DoubleArray10 doubleArray;
and Array<Account,1000> accountArray; works exactly like
class AccountArray1000{
public:
AccountArray1000()= default;
int getSize() const;
private:
Account elem[1000];
};
int AccountArray1000::getSize() const { return 1000; }
AccountArray1000 accountArray;
Related
I'm just getting started with Object Oriented Programming. I'm trying to access member function of two different classes within a template function. I have restricted access to member functions based on boolean flag isAggregateElement. For some reason, Compiler throws error stating that there is no such member function.
class descriptor{
public:
int getName(){
return -5;
}
};
class aggregate{
public:
int getDescription() {
return 234;
}
int getUnit(){
return 1;
}
};
template <typename T>
void buildObjectInfo(const T& classMemberType, const bool& isDataInterface){
T baseTypeElement = classMemberType;
bool isAggregateElement = !isDataInterface;
if(isAggregateElement){
cout<<baseTypeElement.getUnit()<<endl;
} else {
cout<<baseTypeElement.getName()<<endl; // Error gets resolved if I remove the else construct
}
}
int main()
{
aggregate a;
descriptor d;
buildObjectInfo<aggregate>(a,false);
return 0;
}
What should I do to access getUnit() without deleting boolean condition (or) removing else construct in the template function ?
Both branches must be valid. Suppose you call buildObjectInfo(d,false), what should happen then?
You can use constexpr if to discard the false branch.
Note that the getters should be const methods. The template argument can be deduced from the function parameter and you do not need the bool:
#include <iostream>
#include <type_traits>
struct descriptor{
int getName() const { return -5; }
};
struct aggregate{
int getDescription() const { return 234; }
int getUnit() const { return 1; }
};
template <typename T>
void buildObjectInfo(const T& t){
if constexpr(std::is_same_v<aggregate,T>) {
std::cout << t.getUnit() << '\n';
} else {
std::cout << t.getName() << '\n';
}
}
int main() {
aggregate a;
descriptor d;
buildObjectInfo(a);
buildObjectInfo(d);
}
However, for only 2 different types an overloaded function is much simpler:
#include <iostream>
struct descriptor{
int getName() const { return -5; }
};
struct aggregate{
int getDescription() const { return 234; }
int getUnit() const { return 1; }
};
void buildObjectInfo(const aggregate& t) {
std::cout << t.getUnit() << '\n';
}
void buildObjectInfo(const descriptor& t) {
std::cout << t.getName() << '\n';
}
int main() {
aggregate a;
descriptor d;
buildObjectInfo(a);
buildObjectInfo(d);
}
Is there any way to force to only allow const instances of class to be instantiated, and have non-const instances be detected as an error by the compiler?
is there any generic way to take an existing class, and "constify" it by removing all non-const functionality?
One possible workaround is to create a wrapper class that holds an instance of the class and only gives access to a const reference to it.
template<class T>
class Immutable {
public:
template<typename... Args>
Immutable(Args&&... args) : instance(forward<Args>(args)...) {
}
operator const T&() {
return instance;
}
const T& get() const {
return instance;
}
private:
Immutable& operator=(const Immutable& other) = delete;
T instance;
};
Suppose you have a mutable class Class:
class Class {
public:
Class() : m_value(0) {
}
Class(const Class& other) : m_value(other.m_value) {
}
Class(int value) : m_value(value) {
}
Class(int x, int y) : m_value(x + y) {
}
void change(int value) {
m_value = value;
}
int value() const {
return m_value;
}
private:
int m_value;
};
Here is how Immutable<Class> can be used:
void functionTakingConstReference(const Class& x) {
}
void functionTakingNonConstReference(Class& x) {
}
void functionTakingImmutableClass(Immutable<Class>& x) {
}
void functionTakingValue(Class x) {
}
int main(int argc, char *argv[])
{
// Any constructor of Class can also be used with Immutable<Class>.
Immutable<Class> a;
Immutable<Class> b(1);
Immutable<Class> c(2, 3);
Immutable<Class> d(c);
// Compiles and works as expected.
functionTakingConstReference(a);
functionTakingImmutableClass(a);
functionTakingValue(a);
cout << a.get().value() << endl;
// Doesn't compile because operator= is deleted.
// b = a;
// Doesn't compile because "change" is a non-const method.
// a.get().change(4);
// Doesn't compile because the function takes a non-const reference to Class as an argument.
// functionTakingNonConstReference(a);
return 0;
}
Is there any way to force to only allow const instances of class to be instantiated, and have non-const instances be detected as an error by the compiler?
No.
But you can declare all members as const. Then both const and non-const instances would behave largely in the same way and it shouldn't matter whether the instances are const.
I think you are looking for an immutable class. An easy way to get immutability is to declare all member variables as const. This way you ensure that the state of your objects will not change after construction.
This guarantee is independent of whether your object is const and even if you have non-const member functions for that class.
For example:
class Foo
{
public:
Foo(int id, double value) : m_id(id), m_value(value) { }
int Id() const { return m_id; }
double Value() const { return m_value; }
private:
const int m_id;
const double m_value;
};
Another way you could generate an immutable object of any type is through a template class. Something like this:
class Bar
{
public:
Bar(int id, double value) : m_id(id), m_value(value) { }
int Id() const { return m_id; }
double Value() const { return m_value; }
void SetId(int id) { m_id = id; }
private:
int m_id;
double m_value;
};
template<typename T>
class MyImmutable
{
public:
const T m_obj;
MyImmutable(const T& obj) : m_obj(obj)
{ }
};
int main()
{
cout << "Hello World!" << endl;
Foo a(1,2.0);
Bar x(2,3.0);
MyImmutable<Bar> y(x);
cout << "a.id = " << a.Id() << endl;
cout << "a.value = " << a.Value() << endl;
cout << "y.id = " << y.m_obj.Id() << endl;
cout << "y.value = " << y.m_obj.Value() << endl;
y.m_obj.SetId(2); // calling non-const member throws an error.
return 0;
}
Im trying to do a sort for the biggest to the lowest
my Math Vector inherit from Vector
now the Problem is i can't see the inhert function (see below &&&&&)
template <class T>
class Vector
{
protected:
T* Array;
int Size;
int Capacity;
public:
Vector();
Vector(Vector<T>& Copy_Array);
T operator=(const T* Element);
void operator=(const T Element);
T* operator[](const int Index) const;
ostream& operator<<(const Vector<T>& Print_Elements);
void Insert(T Element);/*Push*/
void ReSize(const int New_Size);
T* Pop();
void Set_size(int New_Size);
void Set_Capacity(int New_Capacity);
int Get_Size() const;
int Get_Capacity() const;
T* Top() const;
~Vector();
};
is this the right way to inherit just the function ofcurse(protected)
template<class T>
class MathVector:public Vector<T>/*<- form template to tamplate*/
{
public:
void Sort(const int Direction);
};
&&&&&&/* i can't see the public mathods of vector*/&&&&&&
template<class T>
void MathVector<T>::Sort(const int Direction)
{
this-> &&&&&&/* i can't see the public mathods of vector*/&&&&&&
};
Yes, it is the right way to inherit from your Vector<T>. And to use the public methods write for example
template<class T>
void MathVector<T>::Sort(const int Direction)
{
Vector<T>::yourNonPrivateMethod();
auto test = Vector<T>::yourNonPrivateMember;
};
You may also declare them by using in the header file:
using Vector<T>::yourNonPrivateMethod;
EDIT
Here a simplified example:
#include <iostream>
template<typename T> class Base
{
public:
Base() : member( static_cast<T>( 0 ) ) {};
virtual ~Base() = default;
T member;
void baseMemberFunction()
{
std::cout << "Base<T>::memberFunction()" << std::endl;
}
void anotherBaseMemberFunction()
{
std::cout << "Base<T>::anotherBaseMemberFunction()" << std::endl;
}
};
template<typename T> class Derived : public Base<T>
{
public:
Derived() : Base<T>(), member(1) {}
T member;
using Base<T>::anotherBaseMemberFunction;
void derivedMemberFunction()
{
std::cout << "Derived<T>::derivedMemberFunction()" << std::endl;
Base<T>::baseMemberFunction();
anotherBaseMemberFunction();
std::cout << "Derived<T>::member = " << member << std::endl;
std::cout << "Base<T>::member = " << Base<T>::member << std::endl;
}
};
int main()
{
Derived<int> derived;
std::cout << " --- Call baseMemberFunction --- " << std::endl;
derived.baseMemberFunction();
std::cout << " --- Call derivedMemberFunction --- " << std::endl;
derived.derivedMemberFunction();
return 0;
}
I have a template method inside a template class.
I read that a method can not be specialized without specialize the class before.
But I want to factorize some of theses methods, is it possible ?
Example :
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num> class A {
private:
num n;
public:
template<typename type>
void multiplyBy(); // by 1 if <int> or 1,5 if <float>
}; // A
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<One>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
A stackoverflow related question : C++ specialization of template function inside template class
In particular this comment : C++ specialization of template function inside template class
Have I to deduct than there is no way to factorize multiplyBy(), for one for int and an other for float ?
As english is not my natural language maybe I miss something simple, maybe a workaround with partial-specialization.
Edit : put A::n in private to match even better my problem.
You might use tag dispatching:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num>
class A {
public:
num n;
private:
template<typename> struct Tag {};
void multiplyBy(Tag<int>) {
std::cout << 1.0*n.number << std::endl;
}
void multiplyBy(Tag<float>) {
std::cout << 1.5*n.number << std::endl;
}
public:
template<typename type>
void multiplyBy() {
multiplyBy(Tag<type>());
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
But I want to factorize some of theses methods, is it possible ?
You probably know that you cannot use:
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
without specializing A<One>.
You can do something along the lines of:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num, typename type = int> struct MultiplyBy {
static void doit(num n)
{
std::cout << 1.0*n.number << std::endl;
}
};
template<typename num> struct MultiplyBy<num, float> {
static void doit(num n)
{
std::cout << 1.5*n.number << std::endl;
}
};
template<typename num> class A {
public:
num n;
template<typename type>
void multiplyBy()
{
MultiplyBy<num, type>::doit(n);
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
I have a derived class named TimeWithDate inherited from Date class and Time class.
I try to use the member function by using ::.
like this:
int subtract(TimeWithDate& other_date){
return Date::subtract(other_date) + Time::subtract(other_date);
}
but I got this warning:
Error: a nonstatic member reference must be relative to a specific object.
Then I tried this way:
int subtract(TimeWithDate& other_date){
return *(Date*)this.subtract(other_date) + *(Time*)this.subtract(other_date);
}
and got this warning:
Error: 'this' may only be used inside a nonstatic member function.
What should I do?
whole code
#include<iostream>
using namespace std;
class Time
{
int hour, second, minute;
public:
Time();
Time(int h, int m, int s);
void set(int h, int m, int s);
void increment();
void display();
bool equal(Time &other_time);
bool less_than(Time &other_time);
int subtract(Time &another);
};
class Date
{
int year, month, day;
public:
Date();
Date(int y, int m, int d);
void increment();
bool equal(Date &another);
int subtract(Time &another);
};
class TimeWithDate : public Time, public Date
{
public:
bool compare(TimeWithDate&);
void increment();
int subtract(TimeWithDate&);
};
bool TimeWithDate::compare(TimeWithDate &other_date){
if (Date::equal(other_date) && Time::equal(other_date))
return true;
else return false;
}
void TimeWithDate::increment(){
Time::increment();
Time zero(0, 0, 0);
if (Time::equal(zero))
Date::increment();
}
int subtract(TimeWithDate& other_date){
return Date::subtract(other_date) + Time::subtract(other_date);
}
subtract() should be a member function of class TimeWithDate. It appears that you have it as a non-member/ static function. So, this pointer is no more available in that function.
You need parse your whole code, below works fine in my computer(VS2012).
#include <iostream>
using namespace std;
class Base1
{
public:
void print(const char *str){ cout << "base1 " << str << endl; }
};
class Base2
{
public:
void print(const char *str){ cout << "base2 " << str << endl; }
};
class Derived : public Base1, public Base2
{
public:
void print(const char *str);
};
void Derived::print(const char *str)
{
cout << "Derived " << str << endl;
Base1::print(str);
Base2::print(str);
}
int main()
{
Derived d;
d.print("hello");
return 0;
}