Common Practice for Template Function Defination - Mix with Function Declaration? - c++

Most of the time, I "avoid" to have the following style in my single header file.
class a {
void fun();
};
void a::fun() {
}
In order to avoid the following error. I try to separate class definition in cpp file and class declaration in h file. For example, the below is the wrong example :
main.cpp
#include "b.h"
#include "a.h"
int main()
{
a aa;
b bb;
}
a.h
#ifndef A_H
#define A_H
#include <iostream>
class a {
public:
virtual int fun();
};
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
b.h
#ifndef B_H
#define B_H
#include <iostream>
#include "a.h"
class b {
public:
b();
};
#endif
b.cpp
#include "b.h"
#include "a.h"
b::b()
{
a aa;
aa.fun();
}
I will get the following error :
1>b.obj : error LNK2005: "public: virtual int __thiscall a::fun(void)" (?fun#a##UAEHXZ) already defined in main.obj
However, when come to template, I will usually do it this way :
a.h
#ifndef A_H
#define A_H
#include <iostream>
template <typename T>
class a {
public:
virtual T fun();
};
template<typename T> T a<T>::fun()
{
T t;
std::cout << "a" << std::endl;
return t;
}
#endif
May I know it this a good practice?
Thanks.
Cheok

You can eliminate the LNK2005 error by declaring the definition of a::fun() as inline. For example:
// a.h
// ...
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
With templates, the problem doesn't occur because the compiler/linker take care of ensuring that there is only one definition of each template instantiation.
If, for some reason, you don't want the function to be inline, then you'll have to ensure that it only gets compiled once. For example, something like this:
// a.h
// ...
#ifdef DEFINE_CLASS_A_FUNCTIONS
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
and then, somewhere, you'll need to do something like this (exactly once):
#define DEFINE_CLASS_A_FUNCTIONS
#include "a.h"

1>b.obj : error LNK2005: "public:
virtual int __thiscall a::fun(void)"
(?fun#a##UAEHXZ) already defined in
main.obj
You are getting this error because a::fun() is not inline
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
Also, refer C++ FAQ : How can I avoid linker errors with my template functions?

Related

#include recursion with template

I have problem like there Why can templates only be implemented in the header file? (and there Correct way of structuring CMake based project with Template class) but with include recursion.
Code:
A.h
#pragma once
#include "B.h"
struct A
{
B b;
void doThingA() {}
};
B.h
#pragma once
struct A;
struct B
{
A *a;
template<typename T>
void doThingB();
};
#include "A.h"
template<typename T>
void B::doThingB()
{
a->doThingA();
}
main.cpp
#include "A.h"
int main() {}
Error:
In file included from A.h:2,
from main.cpp:1:
B.h: In member function 'void B::doThingB()':
B.h:16:6: warning: invalid use of incomplete type 'struct A'
16 | a->doThingA();
| ^~
B.h:2:8: note: forward declaration of 'struct A'
2 | struct A;
| ^
B.h includes from A.h but A.h required by template function implementation in B.h does not. I'm also cannot take implementation to an .cpp because of template.
It's possible to solve by using explicit instantiation of templates but I'm wondering for another solution.
When you have types that are this tightly coupled, the simplest solution is to put them in a single header file.
#pragma once
// forward declaration of A
struct A;
// declare B, since A needs it
struct B
{
A *a;
template<typename T>
void doThingB();
};
// now we can declare A
struct A
{
B b;
void doThingA() {}
};
// and finally, implement the parts of B that need A
// and need to be in the header
template<typename T>
void B::doThingB()
{
a->doThingA();
}
If you still want a B.h, then it can be a single line:
#include "A.h"
If you want to split A/B into multiple headers for your own organization, a simple solution is to add compile-time checks to ensure the files aren't included directly.
// A.h
#pragma once
#define A_IMPL
#include "B_impl.h"
#undef A_IMPL
// B.h
#pragma once
#ifndef A_IMPL
#error "B_impl.h can't be included directly; use A.h"
#endif
struct A;
struct B
{
A *a;
template<typename T>
void doThingB();
};
#include "A_impl.h"
template<typename T>
void B::doThingB()
{
a->doThingA();
}
// A_impl.h
#pragma once
#ifndef A_IMPL
#error "A_impl.h can't be included directly; use A.h"
#endif
struct A
{
B b;
void doThingA() {}
};
You can make the #ifdef checks more complicated if you want more of your headers to use the impl files directly, but the public interface remains blissfully unaware.
Based on Stephen's solution I came up with that architecture:
A.h
#pragma once
#define A_H
#include "B.h"
struct A
{
B b;
void doThingA() {}
};
#include "B_impl.h"
B.h
#pragma once
struct A;
struct B
{
A *a;
template <typename T>
void doThingB();
};
#ifndef A_H
#include "B_impl.h"
#endif
B_impl.h
#pragma once
#include "A.h"
template <typename T>
void B::doThingB()
{
a->doThingA();
}
main.cpp
#include "A.h"
int main() {}
So I can include A.h and B.h separately and also it looks cleaner for me.

C++ cyclic dependency of classes (Singleton)

i have a problem to compile the classes with cyclic dependency, and i can not find the way to compile my code
the main problem is appeared in chain of classes that has dependency to each others
for example i have 6 header files(Classes) (A, B, C, D, E, F)
A included in E
F, D included in A
E included in F, D
now i have a loop and cant fix it
i simplify the problem then create the simple example to show what is my exact problem
A.h
#ifndef A_H
#define A_H
#include "B.h"
class A
{
public:
static A& getInstance()
{
static A instance;
return instance;
}
int i;
int sum()
{
return i+B::getInstance().j;
}
private:
A() {}
};
#endif
B.h
#ifndef B_H
#define B_H
#include "A.h"
class B
{
public:
static B& getInstance()
{
static B instance;
return instance;
}
int j;
int sum()
{
return j+A::getInstance().j;
}
private:
B() {}
};
#endif
main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
int main()
{
A::getInstance().i=1;
B::getInstance().j=2;
int t1=A::getInstance().sum();
int t2=B::getInstance().sum();
std::cout<<t1<<std::endl;
std::cout<<t2<<std::endl;
return 0;
}
g++ main.cpp
In file included from A.h:3:0,
from main.cpp:1:
B.h: In member function ‘int B::sum()’:
B.h:17:12: error: ‘A’ has not been declared
return j+A::getInstance().j;
is there any way or solutions to resolve this?
If you can't use .cpp files for some reason, you can do this:
a.h:
#pragma once
class A {
public:
static A& getInstance();
int i;
int sum();
private:
A();
};
a_impl.h:
#pragma once
#include "a.h"
#include "b.h"
inline A& A::getInstance() {
static A instance;
return instance;
}
inline int A::sum() {
return i + B::getInstance().j;
}
inline A::A() {
}
b.h:
#pragma once
class B {
public:
static B& getInstance();
int j;
int sum();
private:
B();
};
b_impl.h:
#pragma once
#include "a.h"
#include "b.h"
inline B& B::getInstance() {
static B instance;
return instance;
}
inline int B::sum() {
return j + A::getInstance().i;
}
inline B::B() {
}
And then first include declarations a.h and b.h, and then implementations a_impl.h and b_impl.h:
#include "a.h"
#include "b.h"
#include "a_impl.h"
#include "b_impl.h"
#include <iostream>
int main() {
A::getInstance().i = 1;
B::getInstance().j = 2;
int t1 = A::getInstance().sum();
int t2 = B::getInstance().sum();
std::cout << t1 << std::endl;
std::cout << t2 << std::endl;
}
Now it will compile. In this particular example, B (or A) could've been implemented inside class definition (so, no b_impl.h). I separated declarations and definitions for both classes for the sake of symmetry.

I need to include two header files to each other not using forward declaration cause get "incomplete type" error

I need to include two header files to each other but I have trouble doing this. Is there any way except using forward declaration and template to do this ? or I'm not allowed to do it in c++?
here is what I want to do:
// A.hpp file
#ifndef H_A_H
#define H_A_H
#include "B.hpp"
class A {
private:
vector<B*> b;
public:
void function() {
// using methods of B
}
};
#endif
// B.hpp file
#ifndef H_B_H
#define H_B_H
#include "A.hpp"
class B {
private:
vector<A*> a;
public:
void function() {
// using methods of A
}
};
#endif
You can't include two header files to each other. There should be forward declaration in one of the files and function definition has to be pushed to .cpp file where you can include the header file.
// HeaderA.h file
#ifndef H_A_H
#define H_A_H
#include "HeaderB.h"
class A {
private:
int b;
public:
void function() {
// using methods of B
B b;
b.function();
}
};
#endif
// HeaderB.h file
#ifndef H_B_H
#define H_B_H
class A;
class B {
private:
int a;
public:
void function();
};
#endif
// Main.cpp
#include "HeaderA.h"
#include "HeaderB.h"
void B::function()
{
// using methods of A
A a;
a.function();
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
You have a cyclic dependency. This answer explains how to deal with them via forward declarations.
This article also deals with cyclic dependencies.
If you 100% don't want to use forward declarations and it is possible you can split logic in a different class and use composition.
// SomeLogic.h
class SomeLogic
{
};
// A.h
#include "SomeLogic.h"
class A
{
SomeLogic someLogic;
};
// B.h
#include "SomeLogic.h"
class B
{
SomeLogic someLogic;
};

Calling Function in MainClass using SubClass

I already saw many answers how to create (e.g.) A class with an object B b and a B class with an object A a
like:
B:
class A;
class B{
A& a;
};
A:
class A{
B b;
};
but if I want to call a function from A in B I got: Invalid use of incomplete type 'class A'
What can I do? I think I know why the compiler say that, but I don't know how to fix it.
Here my latest Code:
Main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
#endif
SubClass.h:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print() { main->printTest(); }
protected:
private:
};
#endif
The main problem with your code is that the definition of MainClass and SubClass are mutually dependent, therefore the use of the header guards will forbid the inclusion of both header files in the same translation unit (i.e. the union of a cpp file and the all the header files included.)
The forward declaration of class MainClass in subclass.h could solve this problem, since the SubClass::main is a pointer (check the PIMPL idiom), but since you have included the implementation of the class methods in the in the header files, the compiler fails when the SubClass::print() method makes a reference to MainClass::printTest() because it knows nothing about the class MainClass except the fact that it is defined somewhere else.
On the other hand, changing the forward declaration with the explicit inclusion of mainclass.h in subclass.h is not a solution, because of the header guards, as said above.
The simple solution is to split the declaration and the implementation of you classes in .h and .cpp files. If you do so, the compiler will work on multiple translation units: one for the mainclass.cpp, one for the subclass.cpp and one for the main.cpp. When processing the subclass.cpp translation unit, the compiler will be able to include the file mainclass.h and will have the complete definition of MainClass to "see" that a MainClass::printTest() method exists.
Here is the mainclass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass
{
SubClass sub;
public:
void print();
void printTest();
};
#endif
the mainclass.cpp file:
#include <iostream>
#include "mainclass.h"
void MainClass::print()
{
sub.print();
}
void MainClass::printTest()
{
std::cout << "test" << std::endl;
}
The subclass.h file:
#ifndef SUBCLASS_H
#define SUBCLASS_H
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
};
#endif
the subclass.cpp:
#include "mainclass.h"
//#include "subclass.h" // already included with the previous line
void SubClass::print()
{
main->printTest();
}
and finally the main.cpp:
#include "mainclass.h"
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
This will compile and will apparently work, because it will print the string "test" even if the main pointer is not initialized, and points to an undefined memory area.
This happens because the printTest method does nothing but producing a side effect, i.e. printing on screen. Indeed it does not access to any data member of the MainClass through the this pointer, and therefore you have no memory access violation. Indeed, invoking a method on a not instantiated pointer is an undefined behavior, so it would be better to avoid it, as well as cyclic dependencies.
You can't call a function (MainClass::printTest) that does not exist yet.
You can declare the function inside the SubClass, but define it after you have the MainClass definition.
#include <iostream>
class MainClass;
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
class MainClass
{
SubClass sub;
public:
void print() { sub.print(); }
void printTest() { std::cout << "test" << std::endl; }
};
void SubClass::print() { main->printTest(); }
int main()
{
MainClass mainClass;
mainClass.print();
return 0;
}
Avoid creating function bodies in H files and put the function body into Cpp file.
MainClass.h:
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <iostream>
#include "subclass.h"
class MainClass {
SubClass sub;
public:
void print();
void printTest();
};
#endif
MainClass.cpp:
#include <iostream>
#include "mainclass.h"
void MainClass :: print () { sub.print(); }
void MainClass :: printTest() {std::cout << "test" << std::endl; }
SubClass.h
#ifndef SUBCLASS_H
#define SUBCLASS_H
#include "mainclass.h"
class SubClass
{
MainClass* main;
public:
void print();
protected:
private:
};
#endif
SubClass.cpp
#include "mainclass.h"
#include "subclass.h"
void SubClass::print ()
{
main->printTest();
}
you can actually #include "mainclass.h" in your subclass.h because it is guarded by #ifdef
You have a design problem:-
How come in SubClass.h compiler will know class MainClass has a method printTest so that it can link to it as you did not included the header file for the definition of MainClass
Another problem is you can not even include MainClass.h in SubClass.h because you are reference to SubClass sub; in it.
MainClass* main; pointer main never initialized and hence this statement void print() { main->printTest(); } is also wrong here.

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>(); }
};