I need to assign unique integer value to each descendant of class Base that should be accessible by using pointer to those classes or its typenames.
I implemented it such way
class Base {
public:
int idCompType = InvalidCompType;
virtual int getCompType() = 0;
}
then in each descendant of base I should declare idCompType (for templates) and override getCompType (for pointers):
class Real1: public Base {
public:
int idCompType = 1;
int getCompType() override { return idCompType; }
}
now I can find comp type from pointer to base
Base *comp = getComp(...);
std::cout << comp->getCompType();
or using typename in template:
template <typename T>
int getType() {
return T::idCompType;
}
Is there a way to make it even simpler without double declaration idCompType and getCompType() in each descendant class? In Object Pascal I achieved this using virtual static methods, but their are not allowed in C++..
PS: the question is not about virtual static methods - virtual static method is just the one of the possible solutions and the way my problem was solved in other language.
My recommendation:
Changes to Base:
class Base {
public:
virtual int getCompType() = 0;
protected:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
Changes to the derived class:
class Real1: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
Here's a working program:
#include <iostream>
class Base {
public:
virtual int getCompType() = 0;
protected:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
class Real1: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
class Real2: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
template <typename T> int getCompType()
{
return T::getCompTypeImpl();
}
int main()
{
Real1 v1;
Real2 v2;
std::cout << v1.getCompType() << std::endl;
std::cout << v2.getCompType() << std::endl;
std::cout << getCompType<Real1>() << std::endl;
std::cout << getCompType<Real2>() << std::endl;
};
Output:
1
2
1
2
Here is a slight variant of #Sahu's version.
Instead of implementing the same getCompTypeImpl() in every derived class, put it in Base class.
template<typename T>
static int getCompTypeImpl()
{
return getNextCompType<T>();
}
Modify getNextCompType() to
template<typename T>
static int getNextCompType()
{
auto iter = m_table.find(std::type_index(typeid(T)));
if (iter != m_table.end())
{
return iter->second;
}
else
{
m_table.insert(std::make_pair(std::type_index(typeid(T)), ++nextType));
return nextType;
}
}
And finally introduce 2 new static data members.
private:
static std::map<std::type_index, int> m_table;
static int nextType;
Please find the full code here.
Admittedly this introduces 2 new static members and does a bit more work
than the original version from Sahu. But, this removes the burden of implementing the methods in
all the derived classes.
Yet another variation of #R Sahu's answer to eliminate duplication of code in the derived classes:
#include <iostream>
class Base {
public:
virtual int getCompType() const = 0;
template <typename T>
static int getCompTypeOf()
{
static int compType = getNextCompType();
return compType;
}
private:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
template <typename Derived, typename DeriveFrom = Base>
class TypeAssigner : DeriveFrom {
public:
int getCompType() const override
{
return Base::getCompTypeOf<Derived>();
}
};
class Real1: public TypeAssigner<Real1> {};
class Real2: public TypeAssigner<Real2> {};
class Real3 : public TypeAssigner<Real3, Real2> {};
int main()
{
Real1 v1;
Real2 v2;
Real3 v3;
std::cout << v1.getCompType() << '\n';
std::cout << v2.getCompType() << '\n';
std::cout << v3.getCompType() << '\n';
std::cout << Base::getCompTypeOf<Real1>() << '\n';
std::cout << Base::getCompTypeOf<Real2>() << '\n';
std::cout << Base::getCompTypeOf<Real3>() << '\n';
};
Related
i would like a class with some members, that each member can changes in a particular class (each member to have two different states in two different classes, writable and read-only). What is the best way to implement the following problem?
class myRepository
{
...
int writableIn_A;
int writableIn_B;
...
};
myRepository repository;
class A
{
...
void f_A()
{
cout << repository.writableIn_A; //ok
cout << repository.writableIn_B; //ok
repository.writableIn_A = 10; //ok
repository.writableIn_B = 20; //compile error
}
...
};
class B
{
...
void f_B()
{
cout << repository.writableIn_A; //ok
cout << repository.writableIn_B; //ok
repository.writableIn_A = 10; //compile error
repository.writableIn_B = 20; //ok
}
...
};
You could make writableIn_A and writableIn_B into member functions that return proxy objects. These objects could then be friends with A and B resp.
#include <utility>
template <class T, class U>
class FriendOf {
public:
friend T;
explicit FriendOf(U& r) : i(&r) {}
operator const U& () const { return *i; }
private: // only available to friends:
template<class V>
U& operator=(V&& v) {
*i = std::forward<V>(v);
return *i;
}
U* i;
};
Then return instances of these proxy objects:
class A;
class B;
class SingletonRepository {
public:
static SingletonRepository& getInstance() {
static SingletonRepository ins;
return ins;
}
auto writableIn_A() { return FriendOf<A,int>(m_writableIn_A); }
auto writableIn_B() { return FriendOf<B,int>(m_writableIn_B); }
private:
SingletonRepository() = default;
int m_writableIn_A = 0;
int m_writableIn_B = 0;
};
And the usage will be pretty similar to what you wanted:
class A {
void f_A() {
std::cout << SingletonRepository::getInstance().writableIn_A(); // ok
std::cout << SingletonRepository::getInstance().writableIn_B(); // ok
SingletonRepository::getInstance().writableIn_A() = 10; // ok
// SingletonRepository::getInstance().writableIn_B() = 20; // error
}
};
class B {
void f_B() {
std::cout << SingletonRepository::getInstance().writableIn_A(); // ok
std::cout << SingletonRepository::getInstance().writableIn_B(); // ok
// SingletonRepository::getInstance().writableIn_A() = 10; // error
SingletonRepository::getInstance().writableIn_B() = 20; // ok
}
};
Demo
The issue is completely unrelated to Singleton. To restrict access you can make things private and to grant a specific class access to the private parts you can make it a friend. For finer control of access of individual members you can inherit from base classes that manage access of only their members:
#include <iostream>
class friend_of_A {
int x = 0;
friend struct A;
public:
int get_x() { return x; }
};
class friend_of_B {
int y = 0;
friend struct B;
public:
int get_y() { return y;}
};
struct TheClass : friend_of_A , friend_of_B {
};
struct A {
A(TheClass& c) {
std::cout << c.get_x() << c.get_y();
c.x = 42;
//c.y = 42; // ERROR
}
};
struct B {
B(TheClass& c) {
std::cout << c.get_x() << c.get_y();
// c.x = 42; // ERROR
c.y = 42;
}
};
With another layer, you could even grant access only to a int& get_x() for write-access while the member itself can be hidden completely. And perhaps the members in the bases should be protected or TheClass be made a friend as well.
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 want to create an adapter class in C++, but the interface that I want to adapt to has several non-virtual methods. Can I still use the regular adapter pattern?
#include <iostream>
using namespace std;
class NewInterface{
public:
int methodA(){ cout << "A\n"; }
virtual int methodB(){ cout << "B\n"; }
};
class OldInterface{
public:
int methodC(){ cout << "C\n"; }
int methodD(){ cout << "D\n"; }
};
class Old2NewAdapter: public NewInterface {
public:
Old2NewAdapter( OldInterface* a ){ adaptee = a; }
int methodA(){ return adaptee->methodC(); }
int methodB(){ return adaptee->methodD(); }
private:
OldInterface* adaptee;
};
int main( int argc, char** argv )
{
NewInterface* NI = new Old2NewAdapter( new OldInterface() );
NI->methodA();
NI->methodB();
return 0;
}
If I have this setup, the output will be "A D" instead of "C D" as it should.
So how can I adapt OldInterface to NewInterface, without rewriting NewInterface so that all methods are virtual?
Can you introduce another class? If you can then you can replace functions that use a NewInterface with an even NewerInterface:
class NewerInterface
{
public:
int methodA()
{
// preconditions
int const result = doMethodA();
// postconditions
return result;
}
int methodB()
{
// preconditions
int const result = doMethodB();
// postconditions
return result;
}
private:
virtual int doMethodA() = 0;
virtual int doMethodB() = 0;
};
class Old2NewerInterface : public NewerInterface
{
public:
explicit Old2NewerInterface(OldInterface& x) : old_(&x)
private:
virtual int doMethodA() { return old_->methodC(); }
virtual int doMethodB() { return old_->methodD(); }
private:
OldInterface* old_;
};
class New2NewerInterface : public NewerInterface
{
public:
explicit New2NewerInterface(NewInterface& x) : new_(&x)
private:
virtual int doMethodA() { return new_->methodA(); }
virtual int doMethodB() { return new_->methodB(); }
private:
NewInterface* new_;
};
My first post here :)
I am having a problem with the following C++ code. I have an ABC class A, and two derived classes B and C. All of them have a static member called id:
using std::cout;
class A
{
private:
friend int bar(A& a);
static const int id = 1;
virtual void foo() = 0;
};
class B : public A
{
private :
friend int bar(A& a);
static const int id = 2;
void foo() { /*Do something*/ }
};
class C : public A
{
private:
friend int bar(A& a);
static const int id = 3;
void foo() { /*Do something*/ }
};
int bar(A& a)
{
return a.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
I was expecting this code to print out 2 and 3 - rather it prints out 1 and 1 (bar() is always using A::id). What am I doing wrong? Any ideas?
Based on the comments below, this the final code I am using. It works, but would love to hear more thoughts :)
#include <iostream>
using std::cout;
class A
{
private:
virtual void foo() = 0;
};
class B : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 2;
void foo() { /*do something*/ }
};
class C : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 3;
void foo() { /*do something*/ }
};
template <typename T>
int bar(T& t)
{
return t.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
a.id will be defined at compile-time as A::id. You would need to define a virtual member (non-static) function in class A and have it overridden in B and C to return their respective ids and call this function in bar.
Is there any way to avoid writing int foo() { return id; } for all the derived classes?
Yes, using templates. For example:
template <typename T>
int foo (T& x)
{
return x.id;
}
However, if id is private, this doesn't reduce the code by all that much.
I have a base class A with a constant static variable a. I need that instances of class B have a different value for the static variable a. How could this be achieved, preferably with static initialization ?
class A {
public:
static const int a;
};
const int A::a = 1;
class B : public A {
// ???
// How to set *a* to a value specific to instances of class B ?
};
You can't. There is one instance of the static variable that is shared by all derived classes.
Static members are unique in the application. There is a single A::a constant in your system. What you can do is create a B::a static constant in B that will hide the A::a static (if you don't use the fully qualified name:
class A {
public:
static const int a = 10;
};
static const int A::a;
class B : public A {
public:
static const int a = 20;
static void test();
};
static const int B::a;
void B::test() {
std::cout << a << std::endl; // 20: B::a hides A::a
std::cout << A::a << std::endl; // 10: fully qualified
}
You can do this with Curiously recurring template pattern (you'll have to lose the const though).
template <typename T>
class A {
public:
static int a;
};
template <typename T>
int A<T>::a = 0;
class B : public A<B> {
struct helper { // change the value for A<B>::a
helper() { A<B>::a = 42; }
};
static helper h;
};
B::helper B::h;
May be we can try this way as below ::
The benefit of the below is that you don't have to write the code multiple times, but the actual generated code might be big.
#include <iostream>
using namespace std;
template <int t>
class Fighters {
protected :
static const double Fattack;
double Fhealth;
static const double Fdamage;
static int count;
public :
Fighters(double Fh) : Fhealth(Fh) { }
void FighterAttacked(double damage) {
Fhealth -= damage;
}
double getHealth()
{
return Fhealth;
}
static int getCount()
{
//cout << count << endl;
return count;
}
};
const double Fighters<1>::Fdamage = 200.0f;
const double Fighters<1>::Fattack = 0.6f;
int Fighters<1>::count = 0;
class Humans : public Fighters<1> {
public :
Humans(double Fh = 250) : Fighters<1>(Fh) { count++; }
};
const double Fighters<2>::Fdamage = 40.0f;
const double Fighters<2>::Fattack = 0.4f;
int Fighters<2>::count = 0;
class Skeletons : public Fighters<2> {
public :
Skeletons(double Fh = 50) : Fighters<2>(Fh) { count++; }
};
int main()
{
Humans h[100];
Skeletons s[300];
cout << Humans::getCount() << endl;
cout << Skeletons::getCount() << endl;
return 0;
}
This is part of my other code example .. don't mind many other data but concept can be seen.