I'm using C++ and I'm having struggle with extern templates. In opposite to C# the whole template implementation is really nasty in C++ :(
template_test.hpp
template<class T>
class CFoo {
public:
T Foo_Func(const T& test);
};
template_test.cpp
#include "Template_Test.hpp"
template<class T>
T CFoo<T>::Foo_Func(const T& test)
{
return test;
}
template_test2.hpp
#include "Template_Test.hpp"
extern template class CFoo<int>;
int Template_Tests();
template_test2.cpp
#include "Template_Test2.hpp"
int Template_Tests()
{
CFoo<int> foo_instance;
//this causes an undefined reference
int res = foo_instance.Foo_Func(1);
return res;
}
why does the linker not find my function. I thought extern templates worked the same why as extern variables.
(Put extern int test; in the header file and int test = 0 in the source file.)
thanks for your support:)
Solution 1
One way to solve this issue is to implements the template class's function without function's definitions. in this case:
template<class T>
class CFoo {
public:
T Foo_Func(const T& test) {
return test;
}
};
And then, you don't even need the extern part. I aware that your programmer sense keep telling you to avoid from this, and always to separate between your class functions' definitions, and their implementation- but in template case in c++, it's the easiest solution for this language's huge problem.
An important thing that you need to know- there is a big different between the solutions for this issue between differnt IDEs, but this easy solution works in most of them (if not always).
Solution 2
Another option, if you still want to separate the implementations from the definitions you can include the .cpp file, as well as the .hpp/.h file:
template_test2.hpp
#include "Template_Test.hpp"
#include "Template_Test.cpp"
/*extern template class CFoo<int>;*/ // Again, you don't need this extern
int Template_Tests();
Solution 3
It is the closest way to the way that you tried. in the end of template_test.cpp file, add the following line:
template class CFoo<int>;
and remove the line extern template class CFoo<int>; from the template_test2.hpp file.
I hope that you will find it helping, Korel.
Related
For a project that I am working on, I need to mock certain classes for testing to test different behaviours of functions. For testing I use gtest. Because I am working on a game, the speed and efficiency of the code is of the essence. Because of this requirement I do not want to mock my classes by using virtual functions, but I want to mock my classes with templates, so the implementation of the classes will be defined at compile time and I do not lose performance at run time. Furthermore, because I want to have the least amount of code bloat in my other header/source files I want to split my files into headers and source files, so that some of the includes can be set in the source file. This approach however comes with a couple of problems.
Because the templated functions are defined in a source file, there will need to be an explicit definition of the classes in the source file. Otherwise these templated functions will throw an 'undefined external symbol' error at compile time. This would not be a problem if I did not have two different projects, one for the game and one for testing, as I can't make an explicit definition of a mock in the test project.
I have tried a couple of solutions, but all of them have drawbacks. I will try to demonstrate what I have done with the following piece of code: (I know and use GMock, but this is an easier example)
//Game project
//Foo.h
<template class Bar>
class Foo
{
public:
Bar bar;
bool ExampleFunction();
}
//Foo.cpp
#include "Foo.h"
<template class Bar>
bool Foo::ExampleFunction()
{
return bar.Func() > 10;
}
//Testing project
//BarMock.h
class BarMock
{
public:
int Func();
int value;
}
//BarMock.cpp
#include "BarMock.h"
Bar::Func()
{
return value;
}
//TestFoo.cpp
#include "Foo.h"
TEST(Tests, TestExample)
{
Foo<BarMock> mocked;
mocked.bar.value = 100;
ASSERT_TRUE(mocked.ExampleFunction());
}
Solution 1: Include cpp file in testing project
This is already error prone, as including a cpp file is usually a no go. But if I only include the cpp file ONCE somewhere in the testing project it will not give me the 'c function already defined' error. This in my opinion is not a solid solution (although it is the solution I am currently using), because if I do need a templated class in 2 locations of my testing project this will (almost) always give an error.
//TestFoo.cpp
#include "Foo.h"
#include "Foo.cpp" // error prone, but does compile
TEST(Tests, TestExample)
{
Foo<BarMock> mocked;
mocked.bar.value = 100;
ASSERT_TRUE(mocked.ExampleFunction());
}
Solution 2: Create definitions in header file
This is less error prone, but comes with some other drawbacks. Like I have stated before I want to keep the bloat to a minimum, but with this solution I will also include all of the headers of the Foo header (say I need in Foo and include foo somewhere, then in somewhere I will also have ).
//Game project
//Foo.h
<template class Bar>
class Foo
{
public:
Bar bar;
bool ExampleFunction()
{
return bar.Func() > 10;
}
}
//Foo.cpp removed
Solution 3: Create virtual functions for mocks
This is my least favourite option, but it should be mentioned. Like I have stated before, this comes with a runtime performance hit and I do not want to change most of my functions to virtual functions. But in this way you will not get errors.
//BarMock.h
class BarMock
{
public:
int Func() override;
int value;
}
//BarMock.cpp
#include "BarMock.h"
Bar::Func() override
{
return value;
}
Which one of these options is the best? Is there any method that I have missed? I would love to hear someone's opinion about this as I could not find a 'good' solution online.
A variation of solution #1 by renaming the files:
Foo.h
#pragma once // or/and header guards
<template class Bar>
class Foo
{
public:
Bar bar;
bool ExampleFunction();
};
Foo.inl (or other extension .inc, .ixx, ...)
#pragma once // or/and header guards
#include "Foo.h"
template <class Bar>
bool Foo<Bar>::ExampleFunction()
{
return bar.Func() > 10;
}
Foo.cpp
#include "Foo.h"
#include "Foo.inc"
#include "Bar.h"
// explicit instantiation
template <> struct Foo<Bar>;
FooTest.cpp
#include "Foo.h"
#include "Foo.inc"
#include "BarMock.h"
// Testing code...
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.
For many times now, I have had problems with the declaration and definition order in C++:
struct A {
void Test() { B(); }
};
void B() {
A a;
}
Of course this can be solved by predeclaring B(). Usually this is good enough to solve any of these problems. But when working with module based header-only libraries or similarily complex include systems, this declaration/definition concept can be really painful. I have included a simple example below.
Nowadays most modern language compilers do a two-pass over the source files to build the declarations in the first pass and process the definitions in the second one. Introducing this scheme into C++ shouldn't break any old code either. Therefore,
Why hasn't this, or a similar approach, been introduced into c++ already?
Are there any relevant clauses in the current standard inhibiting this approach?
Example
This is an example of a module based header library, which has blocking includes because of missing predeclarations. To solve this, the user of the library would have to predeclare the "missing" classes, which is not feasible.
Of course this problem might be solved by using a common include header that orders all declarations before definitions, but with a two-pass this code would also work, no modification required.
oom.h
#pragma once
#include "string.h"
struct OOM {
String message;
};
string.h
#pragma once
#include "array.h"
struct String {
Array data;
};
array.h
#pragma once
struct Array {
void Alloc();
};
#include "oom.h"
void Array::Alloc() { throw OOM(); }
str_usage.cpp
#include "string.h"
int main() {
String str;
}
void f(int);
void g() { f(3.14); }
void f(double);
g currently calls f(int), because it's the only f visible. What does it call in your world?
If it calls f(double), you just broke copious existing code.
If you came up with some rules to make it still call f(int), then that means if I write
void g2() { f2(3.14); }
void f2(double);
and then introduce a worse match for the argument - say, void f2(int); before g2, g2 will suddenly start calling the wrong thing. That's a maintainability nightmare.
A much simpler solution is to separate class definitions from function definitions:
struct A {
void Test();
};
struct B {
A a;
};
inline void A::Test() {
B();
}
There are ambiguities in the C++ grammar that can only be resolved if you know what an identifier refers to.
For example:
a * b;
can be either a multiplication if a is a variable, or a pointer declaration if a is a type. Each of these leads to a different parse tree, so the parser must know what a is.
This means that parsing and name resolution cannot be performed in separate passes, but must be done in one pass, leading to the requirement to pre-declare names.
Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.
Been away from C++ for a few years and am getting a linker error from the following code:
Gene.h
#ifndef GENE_H_INCLUDED
#define GENE_H_INCLUDED
template <typename T>
class Gene {
public:
T getValue();
void setValue(T value);
void setRange(T min, T max);
private:
T value;
T minValue;
T maxValue;
};
#endif // GENE_H_INCLUDED
Gene.cpp
#include "Gene.h"
template <typename T>
T Gene<T>::getValue() {
return this->value;
}
template <typename T>
void Gene<T>::setValue(T value) {
if(value >= this->minValue && value <= this->minValue) {
this->value = value;
}
}
template <typename T>
void Gene<T>::setRange(T min, T max) {
this->minValue = min;
this->maxValue = max;
}
Using Code::Blocks and GCC if it matters to anyone. Also, clearly porting some GA stuff to C++ for fun and practice.
The template definition (the cpp file in your code) has to be included prior to instantiating a given template class, so you either have to include function definitions in the header, or #include the cpp file prior to using the class (or do explicit instantiations if you have a limited number of them).
Including the cpp file containing the implementations of the template class functions works. However, IMHO, this is weird and awkward. There must surely be a slicker way of doing this?
If you have only a few different instances to create, and know them beforehand, then you can use "explicit instantiation"
This works something like this:
At the top of gene.cpp add the following lines
template class Gene<int>;
template class Gene<float>;
In if(value >= this->minValue && value <= this->minValue) the second minValue should be maxValue, no?
Echo what Sean said: What's the error message? You've defined and declared the functions, but you've not used them in anything anywhere, nor do I see an error (besides the typo).
TLDR
It seems that you need an Explicit Instantiation i.e. to actually create the class. Since template classes are just "instructions" on how to create a class you actually need to tell the compiler to create the class. Otherwise the linker won't find anything when it goes looking.
The thorough explanation
When compiling your code g++ goes through a number of steps the problem you're seeing occurs in the Linking step. Template classes define how classes "should" be created, they're literally templates. During compile time g++ compiles each cpp file individually so the compiler sees your template on how to create a class but no instructions on what "classes" to create. Therefore ignores it. Later during the linking step the g++ attempts to link the file containing the class (the one that doesn't exist) and fails to find it ultimately returning an error.
To remedy this you actually need to "explicitly instantiate" the class by adding the following lines to Gene.cpp after the definition of the class
template class Gene<whatever_type_u_wanna_use_t>;int
Check out these docs I found them to be super helpful.