C++: Class - Overloaded Constructors - single variable? - c++

I am not sure how to ask this, but hopefully someone will understand. Lets say I have 3 different classes. Class A, Class B and Class C. Class C should take either Class A or Class B as a parameter in the constructor and store it in a private variable.
This is easy with overloaded constructors. My question is how can Class C automagically use the correct class depending on what constructor was used? (Note these 2 classes are similar, but come from different libraries and thus no shared base class). Is this possible with templates? I do not have a lot of experience with templates.

You can do it quite easy with templates:
class A;
class B;
template<class AorB>
class C
{
public:
C(AorB aorb)
: aorb_(aorb)
{ }
private:
AorB aorb_;
};
What this does is that inside the class C the identifier AorB can be used as any other class, in fact it doesn't even have to be an instance of A or B but can be any class.
Can be used like this:
A myA;
B myB;
C<A> myCWithA(myA);
C<B> myCWithB(myB);
There is however one thing you have to remember when creating classes using templates: The specification and implementation can no longer be split into separate header and source files. All of the code have to be available in the header file.
The syntax of the member functions are also a little different.
Example:
template<class T>
class C
{
public:
...
void someFunction();
};
template<class T>
C<T>::someFunction()
{
...
}

Yes, this is possible with templates:
#include <iostream>
template<class T>
class C {
public:
C(T const& ref) : ref(ref) {}
void doStuff() const {
ref.doStuff();
}
private:
T ref;
};
class A {
public:
void doStuff() const {
std::cout << "A::doStuff" << std::endl;
}
};
class B {
public:
void doStuff() const {
std::cout << "B::doStuff" << std::endl;
}
};
int main() {
C<A> foo((A()));
foo.doStuff();
C<B> bar((B()));
bar.doStuff();
}

Related

Non-template class with a template class as a field without specifying template parameters

Is there a way to have a template class such as this
template<bool state = true>
class A
{
};
and have another class which can accept both A<true> and A<false> as a argument or field, without being a template class itself. Like this:
class B
{
public:
B(A& arg_a)
: a(arg_a)
{}
private:
A& a;
};
int main()
{
A<true> aTrue;
A<false> aFalse;
B bTrue(aTrue);
B bFalse(aFalse);
};
Or is this simply impossible because two objects of the same class with different template arguments are treated as different types by the compiler? Other suggestions on how to design this would also be appreciated. I know this design is possible if I just make the template parameter a class field, but I'd like to know if this can be done using templates parameters.
Or is this simply impossible because two objects of the same class with different template arguments are treated as different types by the compiler?
The two different specializations A<true> and A<false> of the class template A are indeed different types.
You could either overload the constructors of B to allow each of them:
struct B {
B(const A<true>&);
B(const A<false>&);
}
or you could leverage polymorphism with any specialization of A deriving from a common base class:
#include <ios>
#include <iostream>
struct Base {
virtual bool getState() const = 0;
};
template<bool state = true>
struct A : public Base {
bool getState() const override { return state; }
};
struct B {
bool state;
B(const Base& base) : state(base.getState()) {}
};
int main() {
A<true> a1{};
A<false> a2{};
std::cout << std::boolalpha
<< B(a1).state << " " // true
<< B(a2).state; // false
}
Another alternative, as mentioned by #Jarod42 in the comments, is to use std::variant, given that you are using C++17 (or later); particularly, std::variant<A<true>, A<false>>.

Two classes with same, standalone, hidden functionality

There is one file with two separate classes and one function:
int foo(int x) {return x+x;}
class A {
public:
int bar(){return foo(0);}
};
class B {
public:
int bar(){return foo(1);}
};
and they both need to use function
which uses only its argument (not use any data from A or B).
I can declare this function as global. But i would like to hide this function for other files (so this is un visible, unacccesible in other files). So i can declare this function as member function of each class A and B. But this will be code duplicate.
What is the best practice for that?
You can just omit any declarations of foo from any headers, and mark it static or define it in an anonymous namespace.
AB.h
class A { int bar(); };
class B { int baz(); };
AB.cpp
static int foo(int x) { return x+x; }
/* or
namespace {
int foo(int x) { return x+x; }
}
*/
int A::bar() { return foo(1); }
int B::baz() { return foo(2); }
You can simply place the function inside another class that only exists in that file:
class C
{
public:
static void foo(int) {}
};
class A
{
void test1()
{
C::foo(0);
}
};
class B
{
void test2()
{
C::foo(0);
}
};
A & B can access this function now and it's not being declared globally.
You can also put the function in its own namespace:
namespace ABFunctions
{
void foo(int) {}
}
And that is another way of keeping it separated, logically.
If you need to protect access, you can do it this way:
class C
{
friend class A;
friend class B;
private:
static void foo(int) {}
};
class A : C
{
void test1()
{
C::foo(0);
}
};
class B : C
{
void test2()
{
C::foo(0);
}
};
Now, only class A & B will have access to foo(int).
You can create a base class and derive from it. You won't have to duplicate code.
class Base {
virtual ~Base = 0;
protected:
int foo(int x) {return x+x;}
};
class A : public Base {...}
class B : public Base {...}
You can't instantiate an object of Base.
If it does not use any data from A or B, then it probably shouldn't be implemented within A or B. It sounds as if f was some kind of auxiliary function. Perhaps creating a class Utilities and making it a public static function of the utilities class would be better.
In c++ there's no hiding of functions at namespace level, though you can create a utility class that contains only private static functions, and explicitly specify which classes may have access using the friend keyword:
class C {
friend class A;
friend class B;
static void foo(int);
};
int foo(int x) {return x+x;}
class A {
public:
int bar(){return C::foo(0);}
};
class B {
public:
int bar(){return C::foo(1);}
};
Though that's not a very good design pattern, since friend introduces some more maintenance effort, as soon other classes than A or B need to access foo as well.
A probably better pattern is to use an interface as I've sketched out in my Q&A here:
How can I remove/refactor a «friend» dependency declaration properly?
The introduction of interfaces there suffers from the overhead of virtual polymorphism though. Maybe that could be resolved with introduction of static polymorphism via the CRTP.
Regarding a wider view for maintenance and reusing implementation details, why are you trying to hide these as rigorously claimed for the function foo(). Why do you need to hide this implementation detail at all?

Class reference another two classes

I have two classes with some methods with same name.
Can I create third class that accept reference from ony of the other two and in the constructor to set obj variable to A or B type?
class A
{
public:
A();
void f();
};
class B
{
public:
B();
void f();
};
class C
{
public:
C(B&);
C(A&);
??? obj;
};
Maybe you want a template class:
template <typename T>
class C
{
T& obj;
public:
explicit C(T& t) : obj(t) {}
void f() { obj.f(); }
};
And then:
A a;
B b;
C<A> c1(a);
C<B> c2(b);
c1.f();
c2.f();
C++ is a very flexible language and as such provides multiple options for what you are asking for. Each with their own pros and cons.
The first route that comes to mind is to use polymorphism.
You have two routes to choose from: static or dynamic polymorphism.
The Static Polymorphic Route
To use static polymorphism (also known as compile-time polymorphism) you should make C a template class:
template <typename T> class C
{
public:
C(T&);
T& obj;
}
The Dynamic Polymorphic Route
To use dynamic (also known as run-time polymorphism) you should provide an interface:
class Fer
{
public:
virtual ~Fer() {}
virtual void f() = 0;
}
Which A and B would implement:
class A : public Fer
{
public:
A();
void f() overide;
};
class B : public Fer
{
public:
B();
void f() overide;
};
C would then be like this:
class C
{
public:
C(Fer&);
Fer& obj;
}
The Variant Route
There are various libraries that provide classes that can safely hold arbitrary types.
Some examples of these are:
Boost.Any
Boost.Variant
QVariant from Qt
When using such classes you generally need some means of converting back to the actual type before operating on it.
You can have a base class that defines the required interface.
class Base
{
public:
Base();
virtual void f();
};
And you can have derived classes that implement the interface.
class A : public Base
{
public:
A();
virtual void f();
};
class B : public Base
{
public:
B();
virtual void f();
};
The class C then refers to the Base class and can actually accept objects of A or B type.
class C
{
private:
Base& base;
public:
C(Base& b) : base(b) {}
};
It can be easily used then.
int main()
{
B b;
C c(b);
return 0;
}

Polymorphism without virtual in C++ for multi level inheritance

I have a situation where I need to achieve polymorphism without vtable. Here is what I am trying to do
There is a class hierarchy: C extends B, B extends A
The idea is to declare a function pointer in A and constructors of B and C assign their corresponding methods to the function pointer in A
With the code below I am able to achieve polymorphism for class C but not for class B.
Obviously I am missing something here. I am not sure if this is even possible. Greatly appreciate any insights into this problem.
I can do this with the below code
A<C> *c = new C();
c->BasePrint(); //Reached C's Print
but not this
// A<B> *b = new B();
// b->BasePrint(); //Intentionally incorrect to demonstrate the problem.
Is there any way to achieve this?
template <typename T>
class A
{
public:
typedef void (T::*PrintFn)(void);
protected:
PrintFn printFn;
public:
void BasePrint()
{
if(printFn)
(((T*)this)->*printFn)();
}
};
template <typename T>
class B : public A<T>
{
public:
B()
{
printFn = &B::Print;
}
void Print()
{
//Print B
}
};
class C : public B<C>
{
public:
C()
{
printFn = &C::Print;
}
void Print()
{
//Print C
}
};
#include <iostream>
#include <typeinfo>
struct own_type {};
template<template<typename T>class CRTP, typename In, typename D>
struct DoCRTP: CRTP<In> {};
template<template<typename T>class CRTP, typename D>
struct DoCRTP<CRTP, own_type, D>: CRTP<D> {};
template<typename D>
struct A {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
A() {
std::cout << "A<" << typeid(D).name() << ">\n";
self()->print();
}
};
template<typename T=own_type>
struct B:DoCRTP<A, T, B<T>> {
B() {
std::cout << "B<" << typeid(T).name() << ">\n";
}
void print() { std::cout<<"I am a B\n"; }
};
template<typename T=own_type>
struct C:DoCRTP<B, T, C<T>> {
C() {
std::cout << "C<" << typeid(T).name() << ">\n";
}
void print() { std::cout<<"I am a C\n"; }
};
void test() {
std::cout << "Instance of B<>:\n";
B<> b;
std::cout << "Instance of C<>:\n";
C<> c;
}
int main() {
test();
}
Here we have a way you can pass in the most derived class, and if you pass in nothing you are assumed to be the most derived class.
However, there is a problem with your design -- A already fully knows its type situation, so there is no need for virtual behavior! BasePrint could static_cast<T*>(this)->Print() and you'd do away with your overhead.
The fundamental problem you have is that you are storing specific-type member function pointers in your base class A.
A template-less A could store pointers to non-specific type function pointers -- say "static" ones that explicitly take an A* as the first argument. In C++11, you could auto-build these functions from member functions. In C++03, std::bind should let you convert your member function pointers to D to functions that take an A* as the first argument.
You are not specifying the template parameter for B in:
A<B> *b = new B();
as opposed to its declaration:
template <typename T>
class B : public A<T>
You should go with something long the lines of:
A<B<X>> *b = new B<X>();
with X being a non templated type.
I can do this with the below code [...] but not this:
A<B> *b = new B();
b->BasePrint(); //Intentionally incorrect to demonstrate the problem.
Well, the problem here is that B is a class template, and you are not instantiating it. It doesn't have much to do with polymorphism nor with vtables. A class template is just a blueprint (well, a template in fact) for instantiating types by passing arguments to them, but it is not a type per se.
You should use some template arguments when instantiating B. For instance:
A<C>* b = new B<C>();
b->BasePrint();
And you should see this invoking B::Print(). Here is a live example.

Can the type of a base class be obtained from a template type automatically?

I am trying to use template meta-programming to determine the base class. Is there a way to get the base class automatically without explicitly specializing for each derived class?
class foo { public: char * Name() { return "foo"; }; };
class bar : public foo { public: char * Name() { return "bar"; }; };
template< typename T > struct ClassInfo { typedef T Base; };
template<> struct ClassInfo<bar> { typedef foo Base; };
int main()
{
ClassInfo<foo>::Base A;
ClassInfo<bar>::Base B;
std::cout << A.Name(); //foo
std::cout << B.Name(); //foo
}
for right now any automatic method would need to select the first declared base and would fail for private bases.
It's possible with C++11 and decltype. For that, we'll exploit that a pointer-to-member is not a pointer into the derived class when the member is inherited from a base class.
For example:
struct base{
void f(){}
};
struct derived : base{};
The type of &derived::f will be void (base::*)(), not void (derived::*)(). This was already true in C++03, but it was impossible to get the base class type without actually specifying it. With decltype, it's easy and only needs this little function:
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class U>
T base_of(U T::*);
Usage:
#include <iostream>
// unimplemented to make sure it's only used
// in unevaluated contexts (sizeof, decltype, alignof)
template<class T, class R>
T base_of(R T::*);
struct base{
void f(){}
void name(){ std::cout << "base::name()\n"; }
};
struct derived : base{
void name(){ std::cout << "derived::name()\n"; }
};
struct not_deducible : base{
void f(){}
void name(){ std::cout << "not_deducible::name()\n"; }
};
int main(){
decltype(base_of(&derived::f)) a;
decltype(base_of(&base::f)) b;
decltype(base_of(&not_deducible::f)) c;
a.name();
b.name();
c.name();
}
Output:
base::name()
base::name()
not_deducible::name()
As the last example shows, you need to use a member that is actually an inherited member of the base class you're interested in.
There are more flaws, however: The member must also be unambiguously identify a base class member:
struct base2{ void f(){} };
struct not_deducible2 : base, base2{};
int main(){
decltype(base_of(&not_deducible2::f)) x; // error: 'f' is ambiguous
}
That's the best you can get though, without compiler support.
My solutions are not really automatic, but the best I can think of.
Intrusive C++03 solution:
class B {};
class A : public B
{
public:
typedef B Base;
};
Non-intrusive C++03 solution:
class B {};
class A : public B {};
template<class T>
struct TypeInfo;
template<>
struct TypeInfo<A>
{
typedef B Base;
};
I am not aware of any base-class-selecting template, and I'm not sure one exists or is even a good idea. There are many ways in which this breaks extensibility and goes against the spirit of inheritance. When bar publicly inherits foo, bar is a foo for all practical purposes, and client code shouldn't need to distinguish base class and derived class.
A public typedef in the base class often scratches the itches you might need to have scratched and is clearer:
class foo { public: typedef foo name_making_type; ... };
int main() {
Foo::name_making_type a;
Bar::name_making_type b;
}
What's with the base class? Are you a .NET or Java programmer?
C++ supports multiple inheritance, and also does not have a global common base class. So a C++ type may have zero, one, or many base classes. Use of the definite article is therefore contraindicated.
Since the base class makes no sense, there's no way to find it.
I am looking for a portable resolution for similar problems for months. But I don't find it yet.
G++ has __bases and __direct_bases. You can wrap them in a type list and then access any one of its elements, e.g. a std::tuple with std::tuple_element. See libstdc++'s <tr2/type_traits> for usage.
However, this is not portable. Clang++ currently has no such intrinsics.
With C++11, you can create a intrusive method to always have a base_t member, when your class only inherits from one parent:
template<class base_type>
struct labeled_base : public base_type
{
using base_t = base_type; // The original parent type
using base::base; // Inherit constructors
protected:
using base = labeled_base; // The real parent type
};
struct A { virtual void f() {} };
struct my_class : labeled_base<A>
{
my_class() : parent_t(required_params) {}
void f() override
{
// do_something_prefix();
base_t::f();
// do_something_postfix();
}
};
With that class, you will always have a parent_t alias, to call the parent constructors as if it were the base constructors with a (probably) shorter name, and a base_t alias, to make your class non-aware of the base class type name if it's long or heavily templated.
The parent_t alias is protected to don't expose it to the public. If you don't want the base_t alias is public, you can always inherit labeled_base as protected or private, no need of changing the labeled_base class definition.
That base should have 0 runtime or space overhead since its methods are inline, do nothing, and has no own attributes.
Recently when I reading Unreal Engine source code, I found a piece of code meet your requirement.
Simplified code is below:
#include <iostream>
#include <type_traits>
template<typename T>
struct TGetBaseTypeHelper
{
template<typename InternalType> static typename InternalType::DerivedType Test(const typename InternalType::DerivedType*);
template<typename InternalType> static void Test(...);
using Type = decltype(Test<T>(nullptr));
};
struct Base
{
using DerivedType = Base;
static void Print()
{
std::cout << "Base Logger" << std::endl;
}
};
struct Derived1 : Base
{
using BaseType = typename TGetBaseTypeHelper<Derived1>::Type;
using DerivedType = Derived1;
static void Print()
{
std::cout << "Derived1 Logger" << std::endl;
}
};
struct Derived2 : Derived1
{
using BaseType = typename TGetBaseTypeHelper<Derived2>::Type;
using DerivedType = Derived2;
static void Print()
{
std::cout << "Derived2 Logger" << std::endl;
}
};
int main()
{
Derived1::BaseType::Print();
Derived2::BaseType::Print();
}
Using a macro below to wrap those code make it simple:
#define DECLARE_BASE(T) \
public: \
using BaseType = typename TGetBaseTypeHelper<T>::Type; \
using DerivedType = T;
I got confused when first seeing these code. After I read #Xeo 's answer and #juanchopanza 's answer, I got the point.
Here's the keypoint why it works:
The decltype expression is part of the member declaration, which does
not have access to data members or member functions declared after
it.
For example:
In the declaration of class Derived1, when declaring Derived1::BaseType, Derived1::BaseType doesn't know the existence of Derived1::DerivedType. Because Derived1::BaseType is declared before Derived1::DerivedType. So the value of Derived1::BaseType is Base not Derived1.