Resolving cyclic dependency with one template in C++ - c++

This looks simple, but I have no good idea to solve this. Minimal example:
template<class T>
struct C {
typename T::t var;
};
class B;
struct A : public C<B> {
typedef int t;
};
struct B
{
A a;
};
int main() { return 0; }
I know that it can be solved by giving C less of B:
template<class t>
struct C {
t var;
};
struct A : public C<int> {
};
But this does not satisfy (especially because B has a lot of such typedefs and static functions I really need in C). Any better idea to resolve this?

If you can make A a template, then the following ought to work...
template<class T>
struct C {
typename T::t var;
};
template <typename BaseType>
struct A : public C<BaseType> {
int i;
};
struct B
{
typedef int t;
A<B> a;
};
typedef A<B> AType;
int main() {
AType a;
a.i = 1;
a.var = 1;
B c;
c.a.i =0;
return 0;
}

First if you want a class to be a base class, its type must be complete, like
struct A : public C<B>
in this case B must be complete type.
Second, if you declare a class type member its type need to be complete unless you define a pointer.
struct B
{
A a; // A must be complete type
};
So you can't have A inheriting from B and B having in as member. But you could convert one to pointer. For sample, below should be fine:
class A;
struct B
{
A* a; // imcomplete type is fine
typedef int t;
};
struct A : public C<B> {
};
Normally if you face this kind of issue, that means there is a design issue in your classes. Maybe you are making monolith classes.
If you follow good guide line:
1 one class (or function), one responsibility.
2 Where possible, prefer writing functions as nonmember nonfriends.
You will have less this kind of issues.

Related

Is it possible to append a structure at a particular offset in its derived class in c++?

Just wanted to ask if it's possible to append a struct at a particular offset, in its derived class?
Example -
struct A
{
int a;
char b;
};
struct B : A
{
int c; // place this before b?
};
No you can't circumvent the way a compiler is required to order the members.
But you could base a solution on
template<typename A> struct B
{
int c;
A a;
};
And you could instantiate an instance with say
B<A> foo;
Even then though, there may be padding between c and a.
It's not possible without changing the A struct unfortunately. You can achieve this by making the A struct more customizable:
template<typename T = void>
struct A {
int a;
T c;
char b;
};
template<>
struct A<void> {
int a;
char b;
};
// v------ Adds the int as the C member
struct B : A<int> {};
// v----- Add no member
struct C : A<> {};

Saving template information in Subclass

I have a parent-class with a function. In this function I want to call a template method but the type of the template depends on the type of sub-class. So I want to save the information about T there. I can't call foo with a template because it's from another part of the Program wich i can't change
class A
{
//this will be called on an instance of B or C, A will never be
//instantiated
void foo()
{
ba<T>();
}
}
class B :public A
{
//T want to save here the Type of T so i won't have to call foo() with
//a template
}
class C :public A
{
//here comes another Type for T
}
What you need is a CRTP pattern, which is very common in C++ template programming.
template<class T>
void ba() {}
template<class Derived>
struct A
{
void foo() {
ba<typename Derived::MyT>();
}
};
struct B
: public A<B>
{
using MyT = int;
};
struct C
: public A<C>
{
using MyT = double;
};
int main() {
B b;
b.foo();
C c;
c.foo();
}
You will need to add a template parameter to the base class A and then specify the type in the declaration of B and C. See the example below:
template <typename T>
class A
{
public:
void foo()
{
ba<T>();
}
};
class B : public A<int>
{
};
class C : public A<bool>
{
};
int main()
{
B b;
C c;
b.foo(); // This calls ba<int>()
c.foo(); // This calls ba<bool>()
return 0;
}
It might be good to spend some time reviewing how templates and inheritance work.
Inheritance
Templates

Overriding pointer to base class with pointer to derived class while inheriting

I'm not sure if the following code is going to do what I expect it to:
struct Foo
{
// Some variables
};
struct Bar : public Foo
{
// Some more variables
};
struct Baz : public Foo
{
// Some more variables
};
class ExampleBase
{
Foo* A;
int B;
double C;
};
class ExampleBar : public ExampleBase
{
Bar* A;
}
class ExampleBaz : public ExampleBase
{
Baz* A;
}
void DoStuff(ExampleBase& example)
{
// Does things with the Foo*, doesn't need to know what inherited type it is
}
What happens when I have the same name for a pointer (A), which is derived from the same class, but is redefined in the derived Example classes?
I've tried templating the example class like this in order to avoid any ambiguity:
template <typename T>
class ExampleBase
{
T* A;
int B;
double C;
}
And then not deriving any classes from it. When I did this however, I can't get the DoStuff() function to compile. since I want it to accept any of the possible derived types.
Edit: The answers from the possible duplicate explain what happens, but don't solve the issue of a function using the base version
You may want to use a template for to implement DoStuff:
template<typename T>
void DoStuff(ExampleBase<T>& example)
{
// Does things with the T*
}
Alternatively, you can expose both the template and the polymorphic interface separately:
struct ExampleBase
{
int B;
double C;
virtual Foo* getA();
};
template<typename T>
struct ExampleTBase : ExampleBase
{
T* A;
Foo* getA() override { return A; }
};
void DoStuff(ExampleBase& example)
{
// Does things with the getA(), that returns a Foo*
}

Conditionally inherit from pure base class

Suppose I have the following class definitions
struct base {
virtual int f() = 0;
};
struct A: public base {
int f() final { return 1; }
};
struct B: public base {
int f() final { return 2; }
};
Is it possible to turn A and B into templates that take a bool parameter that specifies whether to inherit from the base or not? I have usage cases that do or don't require a base class providing a common interface.
Assume that A and B have a lot of member functions, so duplicating implementation would be tedious. But sizeof(A) and sizeof(B) are small.
Sure:
template <bool> struct A
{
// ...
};
template <> struct A<true> : base
{
// ...
};
(Note that you could make A<true> derive from A<false> if that avoids redundancy.)
For example:
template <bool> struct A
{
void f() { std::cout << "A::f called\n"; }
};
template <> struct A<true> : A<false>, base
{
void f() override { A<false>::f(); }
};
int main()
{
A<false> a1;
A<true> a2;
a1.f();
a2.f();
static_cast<base&>(a2).f();
}
I came up with the more direct approach I was looking for, without code duplication.
struct base {
virtual int f() = 0;
};
struct empty_base { };
template <bool Inherit>
struct A final: public std::conditional_t<Inherit,base,empty_base> {
int f() { return 1; }
};
Since you are using a pure base class the distinction shouldn't be important as your optimizer will avoid the virtual function call when you call A::f() since there will never be a derived class that implements a different version of f().
Also you can instead do class A final : base if you don't plan on inheriting from A to avoid having to add final to each function.

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.