Template methods calling each other in C++ - c++

I've got 2 classes with methods that call each other. One of them is a template method:
// Foo.h
class Foo {
public:
void foo_method() {
Bar::bar_method();
}
template <typename U>
static void foo_other_method() {
// some code
}
};
// Bar.h
class Bar {
public:
static void bar_method() {
Foo::foo_other_method<int>();
}
};
And I call it like this:
Foo f;
f.foo_method();
How should I arrange the #include directives in Foo.h and Bar.h so this code compiles?

Move the implementation of Foo::foo_method() so that the definition of Bar is available.
Since it is not a function template, you can move it to a .cpp file.
Foo.h:
#pragma once
class Foo {
public:
void foo_method();
template <typename U>
static void foo_other_method() {
// some code
}
};
Bar.h:
#pragma once
// Need this so Foo::foo_other_method() can be used.
#include "Foo.h"
class Bar {
public:
static void bar_method() {
Foo::foo_other_method<int>();
}
};
Foo.cpp:
#include "Foo.h"
#include "Bar.h"
void Foo::foo_method()
{
Bar::bar_method();
}

Related

Template wrangling

I'm having an issue where I've created a somewhat tangled hierarchy involving templates. The result is I'm having to put some code in the wrong header files just to get it to compile, and compilation is now fragile (I don't know if I can keep this project compiling if just the right function needs to be added.)
So I'm looking for a way to resolve this so that the code is nicely divided into proper files.
So without further ado, here is the code:
TemplatedBase.h
template <typename T> struct TemplatedBase
{
T value;
void go();
};
Derived.h
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};
template <typename T> void TemplatedBase<T>::go()
{
// TemplatedBase<T> NEEDS USE OF Derived!!
// So TemplatedBase<T>::go() is appearing here in Derived.h,
// that's the only way I could get it to compile and it seems really
// out of place here.
Derived der;
der.hello();
}
main.cpp
#include <stdio.h>
#include "Derived.h"
int main(int argc, const char * argv[])
{
Derived d;
d.go();
return 0;
}
Isn't there a way I can put TemplatedBase<T>::go() into a file like TemplatedBase.cpp? Alas, it doesn't seem to work (you will see Undefined symbol: TemplatedBase<int>::go() in XCode at least).
You could do it by explicitly instantiating the template with a particular type in the cpp file:
// TemplatedBase.cpp
#include "TemplatedBase.h"
#include "Derived.h"
template <typename T>
void TemplatedBase<T>::go()
{
// TemplatedBase<T> NEEDS USE OF Derived!!
// So TemplatedBase<T>::go() is appearing here in Derived.h,
// that's the only way I could get it to compile and it seems really
// out of place here.
Derived der;
der.hello();
}
template struct TemplatedBase<int>; // This will make it work but now you can only use `TemplatedBase<int>`
// More instantiations go here...
But I wouldn't recommend doing this as this restricts what types you are able to use in TemplatedBase<T> (You'd have to manually add every single type yourself). So instead, use a templated type inside the go() member function (The trick here is that template parameters are not evaluated immediately):
// TemplatedBase.h
struct Derived; // Forward declaration
template <typename T>
struct TemplatedBase
{
T value;
void go()
{
go_impl();
}
private:
template <typename X = Derived>
void go_impl()
{
X der;
der.hello();
}
};
// Derived.h
#include "TemplatedBase.h"
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};
Note: BTW, since C++20, one can just do:
// TemplatedBase.h
struct Derived; // Forward declaration
template <typename T>
struct TemplatedBase
{
T value;
void go()
{
[] <typename X = Derived>() {
X d;
d.hello();
}();
}
};
TemplatedBase and Derived are really coupled, so sharing the same header might be a viable option.
Else, you can create a file for your template definition (Header guards omitted):
// TemplatedBase.h
// Public header
#include "TemplatedBaseDecl.h"
#include "TemplatedBaseImpl.h"
// TemplatedBaseDecl.h
template <typename T>
struct TemplatedBase
{
T value;
void go();
};
// TemplatedBaseImpl.h
#include "TemplatedBaseDecl.h"
#include "Derived.h"
template <typename T> void TemplatedBase<T>::go()
{
Derived der;
der.hello();
}
// Derived.h
// Public header
#include "TemplatedBaseDecl.h" // Cannot use "TemplatedBase.h"
struct Derived : public TemplatedBase<int>
{
void hello()
{
printf("HI %d\n", value);
}
};

Swig wrapper for class inheriting from specialized template type results in missing methods

I'm using Swig 1.4.1 to wrap some C++ code for a C# project.
Consider the following code which is in one file Foo.h.
#ifndef __Foo__
#define __Foo__
namespace Ogre
{
template<int foo, typename T> class FooBase
{
public:
int getFooBase() const
{
return 1;
}
};
struct FooSpecialized : public FooBase<4, double>
{
int getFooSpecialized() const
{
return 2;
}
};
class FooImpl : public FooSpecialized
{
public:
int getFooImpl() const
{
return 3;
}
};
}
#endif
For that I use the following in my Swig interface file.
%include "Foo.h"
As a result of that, I'm getting access to the methods getFooSpecialized() and getFooImpl(). But getFooBase() is missing.
I get no warnings when compiling my Swig interface file.
That can easily be seen by looking at the genrated C# files. There is one file FooSpecialized.cs which contains
public class FooSpecialized : global::System.IDisposable {
...
public int getFooFooSpecialized() {
int ret = OgrePINVOKE.FooSpecialized_getFooFooSpecialized(swigCPtr);
if (OgrePINVOKE.SWIGPendingException.Pending) throw OgrePINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
and FooImpl.cs which contains
public class FooImpl : FooSpecialized {
...
public int getFooImpl() {
int ret = OgrePINVOKE.FooImpl_getFooImpl(swigCPtr);
if (OgrePINVOKE.SWIGPendingException.Pending) throw OgrePINVOKE.SWIGPendingException.Retrieve();
return ret;
}
}
I tried %rename and %template so far but it's not working.
I also read about splitting the file, but that is no option for me, because it's a third party component I'm working with.
The key is the use and position of %template. Use your Foo.h as is, the following test.i file works:
%module test
%{
#include "Foo.h" // Adds Foo.h to the generated code.
%}
// Declare to SWIG the FooBase class interface.
namespace Ogre
{
template<int foo, typename T> class FooBase
{
public:
int getFooBase() const;
};
// Now that SWIG knows the template, declare an instantiation of
// the template you want to use.
%template(FooBase4dbl) FooBase<4,double>;
// Declare the class interfaces that uses the template instance
struct FooSpecialized : public FooBase<4, double>
{
int getFooSpecialized() const;
};
class FooImpl : public FooSpecialized
{
public:
int getFooImpl() const;
};
}
If you are willing you can refactor the header to reduce code duplication:
FooBase.h
#ifndef __FooBase__
#define __FooBase__
namespace Ogre
{
template<int foo, typename T> class FooBase
{
public:
int getFooBase() const
{
return 1;
}
};
}
#endif
Foo.h
#ifndef __Foo__
#define __Foo__
#include "FooBase.h"
namespace Ogre
{
struct FooSpecialized : public FooBase<4, double>
{
int getFooSpecialized() const
{
return 2;
}
};
class FooImpl : public FooSpecialized
{
public:
int getFooImpl() const
{
return 3;
}
};
}
#endif
test.i
%module test
%{
#include "Foo.h"
%}
%include "FooBase.h"
%template(FooSpec) Ogre::FooBase<4,double>;
%include "Foo.h"
Demo (I'm set up for Python):
>>> import test
>>> f=test.FooImpl()
>>> f.getFooBase()
1

Two template classes with methods calling each other

Two template classes have two methods each which call the other class's method:
// Foo.h
template<typename T>
class Foo {
public:
static void call_bar() {
Bar<int>::method();
}
static void method() {
// some code
}
};
// Bar.h
template<typename T>
class Bar {
public:
static void call_foo() {
Foo<int>::method();
}
static void method() {
// some code
}
};
How can I get this to work? Simply adding #include "Bar.h" to Foo.h (or vice versa) doesn't work because each class needs the other one.
EDIT: I also tried forward declarations, but it still fails at linking stage:
// Bar.h
template <typename T>
class Foo {
public:
static void method();
};
// Foo.h
template <typename T>
class Bar {
public:
static void method();
};
When you have two class templates that are dependent on each other, using two .h files does not make sense. In order to be able to use Foo, you need both Foo.h and Bar.h. In order to be able to use Bar, you also need both Foo.h and Bar.h. It's best to put them in one .h file.
Define the classes.
Implement the member functions at the end.
FooBar.h:
template<typename T>
class Foo {
public:
static void call_bar();
static void method() {
// some code
}
};
template<typename T>
class Bar {
public:
static void call_foo();
static void method() {
// some code
}
};
template<typename T>
void Foo<T>::call_bar() {
Bar<int>::method();
}
template<typename T>
void Bar<T>::call_foo() {
Foo<int>::method();
}

Circular dependency with template function

I have a class A with the following declaration (A.h file):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
and a class B deriving from that class (B.h file):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
So far, so good. My issue is that the function A::doThat() uses B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.
Here are the solutions I have envisioned so far:
Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).
After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.
Is there a neat way to solve this problem?
EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.
A default template parameter for the B class could work:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
The following does work with g++:
File A.h:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
File B.h:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
File test_A.cpp:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
File test_B.cpp:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
Alternative Idea:
I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:
You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).
This cries for polymorphism. There are two options using polymorphism:
Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:
struct A
{
virtual void do_this() const = 0;
template<typename T>
void doThat() const { doThis(); }
};
struct B : A
{
void doThis() const override { /* ... */ }
};
Of course, this only works if doThis() is not templated. If you need that, you could use
Static polymorphism, i.e. CRTP, when
template<typename Derived>
struct A
{
template<typename T>
void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
};
struct B : A<B>
{
template<typename T>
void doThis() const { /* ... */ }
};
If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};

C++ circular dependency issue with function templates

I have several classes in a project I'm working on; the first is a Solver class, originally with a function template whose full definition is in the Solver header file, like so (just showing the bare necessities):
solver.h
class Solver {
public:
template<typename T>
void solve(T t);
}
template<typename T>
void Solver::solve(T t) {
// implementation here
}
Now, class A is used as template parameter for the solve function template as follows:
A.h
#include "solver.h"
class A {
private:
Solver s; //s is instantiated in constructor
public:
void doSomething();
}
A.cpp
void A::doSomething() {
s.solve<A&>(*this);
}
So this is all fine and dandy as it is now, but for the purposes of the project, I need to move the definition of the solve() function template into an implementation file (solver.cpp) from the header file. As I understand it, I can do this as long as I add lines that explicitly state what types will be used with the function template, as follows:
solver.cpp
template<typename T>
void Solver::solve(T t) {
// implementation here
}
template void Solver::solve<A&>(A& a);
However this doesn't work when I try to compile solver, because in order to specify A as a type I want to use as a template parameter in solve.cpp, I need to have A not be an incomplete type. But A requires Solver in order to even compile - so I believe I have a circular dependency. Is there any way I can get around this issue?
I'm relatively new to all this, so take it easy on me please :) Much thanks.
Samoth is nearly right, you need class A; ("forward declaration"). But only before you use it, not before the Solver class:
Edited In response to comments, your minimal code sample was too minimal :) The real problem was Header Guards:
#ifndef SOLVER_H_INCLUDED_
#define SOLVER_H_INCLUDED_
class Solver {
public:
template<typename T>
void solve(T t);
};
#endif // SOLVER_H_INCLUDED_
And
// A.h
#ifndef A_H_INCLUDED_
#define A_H_INCLUDED_
#include "Solver.h"
class A {
private:
Solver s; //s is instantiated in constructor
public:
void doSomething();
};
#endif // A_H_INCLUDED_
// Solver.cpp
#include "Solver.h"
#include "A.h"
template<typename T>
void Solver::solve(T t) {
// implementation here
}
// explicit instantiations
template void Solver::solve<int>(int);
// ...
template void Solver::solve<A&>(A&);
This will work
// main.cpp
#include "A.h"
int main()
{
A a;
a.doSomething();
}
The best way to pass-by circular dependencies is to do this :
class A; // before the class Solver
class Solver {
public:
template<typename T>
void solve(T t);
}
template<typename T>
void Solver::solve(T t) {
// implementation here
}
What you can do is:
solver.h
#ifndef SOLVER_H_INCLUDED_
#define SOLVER_H_INCLUDED_
class Solver {
public:
template<typename T>
void solve(T t);
};
#include "solver.cpp"
#endif
solver.cpp
#include "solver.h"
template<typename T>
void Solver::solve(T t) {
// implementation here
}
and a.hpp
#ifndef A_H_INCLUDED_
#define A_H_INCLUDED_
#include "solver.h"
class A {
private:
Solver s; //s is instantiated in constructor
public:
void doSomething()
{
s.solve(*this);
}
};
#endif