Defining template class member functions in a namespace? - c++

I looked around and tried to find an answer to this. Is it possible to define the member functions of a template class in a namespace within a cpp file? I get an error when I try to do it.
Here are the two files I am trying to compile.
ArrayList.hpp
template<typename T>
class ArrayList{
ArrayList();
~ArrayList();
}
ArrayList.cpp
#include "ArrayList.hpp"
namespace{
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
Compiler error
error: cannot define or
redeclare 'ArrayList<T>' here because namespace '' does not enclose
namespace 'ArrayList'
ArrayList<T>::ArrayList()

You need to declare your class in the same namespace as you define its member functions.
And you are missing a template<typename T> before your destructor.
namespace ANamespace
{
template<typename T>
class ArrayList
{
ArrayList();
~ArrayList();
};
template<typename T>
ArrayList<T>::ArrayList()
{
/* function body goes here */
}
template<typename T>
ArrayList<T>::~ArrayList()
{
/* function body goes here */
}
}

Is it possible to define the member functions of a template class in a namespace within a cpp file?
No, that's not possible. As with any other class declarations the member function declarations and their definitions must appear in the same namespace.
Also unnamed namespaces as used in your example will be seen only in that particular translation unit.
You generally can't put template definitions to separate translation units (unless you have particular specialization cases). Read more about this here please:
Why can templates only be implemented in the header file?
How to fix it?
Just move everything out to your header file and drop the unnamed namespace like this:
ArrayList.hpp
template<typename T>
class ArrayList{
ArrayList();
~ArrayList();
}; // Semicolon at end of class declaration is essential
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
template<typename T> // <<<<< Repeat for evey function definition
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
If you really want to have a namespace, just provide a named one and enclose everything from above (still in the header):
namespace MyUtilities {
template<typename T>
class ArrayList{
public: // <<<<<< Allow access to these functions
ArrayList();
~ArrayList();
};
template<typename T>
ArrayList<T>::ArrayList(){
/* function body goes here */
}
template<typename T>
ArrayList<T>::~ArrayList(){
/* function body goes here */
}
}
See the fully working example here please.
Also to make that stuff usable use the public keyword as shown above.

Firstly you cannot define a template class's methods in a .cpp file. You need to define template class methods in the header file itself (or in another file and then import that via preprocessor includes in the header file itself) For more see Why can templates only be implemented in the header file?
Anonymous namespaces namespace { are used to define things that have internal linkage, i.e. similar to the effect static has on functions defined in implementation files. Read this for more information Why are unnamed namespaces used and what are their benefits?
But in your case you want to define the class methods to be externally visible because you have them declared publicly in the header file. So you probably don't want to have those definitions be in an anonymous namespace.
If you have a namespace enclosing your class in your header file, for example namespace array_list then you should just define your class methods in that same namespace in the header file itself since it's a template class and needs to be visible wherever used.

Related

How do you forward declare header files?

I'm trying to forward declare the header files #include<memory_resource> and #include<deque>. But the following doesn't seem to work. This is pseudo-code:
A.hpp
class memory_resource;
class deque;
class A
{
public:
...
private:
std::pmr::deque<index_t> tempQueue;
}
A.cpp
#include<memory_resource>
#include<deque>
...
No, you cannot "forward declare header files".
In order to define a member of a given type, that type must first be defined. You can achieve that by including the header that defines it.
Since you define the class A in A.hpp and that class has a member of type std::pmr::deque<index_t>, you must include the definition of std::pmr::deque into A.hpp, before the definition of the class A.
Here is a working example:
// A.hpp
#include <deque>
#include <memory_resource>
using index_t = int;
class A
{
std::pmr::deque<index_t> tempQueue;
};
For a rule of thumb, you should not forward declare anything from the standard library, unless the class specifically says it can be forward declared.
To use anything from the standard library, you must actually include them:
// A.hpp
#include <memory_resource>
#include <deque>
class A {
std::pmr::deque<index_t> tempQueue;
}
Now, let's pretend you are not forward declaring anything from the standard library. You don't forward declare header files, instead you forward declare classes.
So if you have a class named deque defined in my_deque.cpp file, in another file, you might do:
// my_deque.cpp
class deque { /* some definitions ... */ };
// A.hpp
class deque;
You don't forward declare the file, my_deque, instead you forward declare the class deque .
Secondly, the deque class was actually located in a namespace. So in order to forward declare deque in another file, you must declare it within the same namespace:
// my_deque.cpp
namespace my_std::pmr{
class deque { /* some definitions ... */ };
}
// A.hpp
namespace my_std::pmr{
class deque;
}
Third, deque was actually a templated class, so to forward declare it, you must also declare it along all the template argument, including anything with default arguments:
// my_deque.cpp
namespace my_std::pmr{
template<typename T, typename Allocator = std::allocator<T>>
class deque { /* some definitions ... */ };
}
// A.hpp
namespace my_std::pmr{
template<typename T, typename Allocator = std::allocator<T>>
class deque;
}
Fourth, you cannot use a forward declared class as a class member directly. In order to create a class, you must be able to calculate the size of the class. To do that, you must also know the sizes of each class members. However, you can't know the size of a forward declared class, because you don't know what members does that class have, so you can't use a forward declared class as a class member.
However, you can use a pointer of a forward declared class as a class member, since all pointers have the same size:
// my_deque.cpp
namespace my_std::pmr{
template<typename T, typename Allocator = std::allocator<T>>
class deque { /* some definitions ... */ };
}
// A.hpp
namespace my_std::pmr{
template<typename T, typename Allocator = std::allocator<T>>
class deque;
}
class A{
my_std::pmr::deque<index_t>* p_tempQueue;
}

Declare in global namespace when defining a method in some namespace?

My code contains two parts - a class template test inside namespace my, and a function frobnicate in a global namespace. The class template wants to use this function in one of its methods, and I want to declare it near its use:
namespace my
{
template <class T>
struct test
{
void do_stuff(T& i)
{
void frobnicate(T&);
frobnicate(i);
// more code here
}
};
}
struct SomeClass {};
void frobnicate(SomeClass& i)
{
// some code here
}
int main()
{
my::test<SomeClass> t;
SomeClass object;
t.do_stuff(object);
}
This works in MS Visual Studio 2017 due to a bug (described here), because Visual Studio declares the function in the global namespace, while according to the Standard, such declaration declares the function in current namespace.
However, gcc rightfully complains:
... undefined reference to `my::frobnicate(SomeClass&)'
Can I make it work in gcc or any other standard-compliant compiler?
If I put the declaration of frobnicate before declaring template test, the code works. However, in my real code, these two parts of code are in unrelated header-files, and I want my code to work regardless of the order of #includes, if possible.
Just forward declare your frobnicate function as a template before the namespace.
template <class T>
void frobnicate(T&);
namespace my {
template <class T>
struct test
{
void do_stuff(T& i)
{
frobnicate(i);
// more code here
}
};
} // close my namespace
I think you could simply declare frobnicate in seperate file and include it before creating namespace my.Or you could declare the function as a macro with #define in the same file. Then you can call frobnicate in the do_stuff in my.
Otherwise you can't call an undefined function.

How to include my implementation in cpp file for some header file (nested classes)

I faced a problem while trying to arrange my project files C++
simply I'm designing a specific template class Mystackt and I want to include entire class inside the public part of Mystackt as an iterator class MyIterator{};
I wrote all of this stuff in my header file MyTemplate.h
so briefly it will appear as following
template <class Type> /* that's in file **MyTemplate.h** */
class MyStackt
{
friend somefunction (int,string,bool);
public:
class iterator
{
public:
iterator();
void somefunc(param1,param2.....);
void otherfunc(...);
private:
Type* ptr;
};
int public_func_of_stackt(void);
void an-otherfunc(int,string,Type,...etc);
private:
int x;
string y;Type* val;
};
Now let's see he cpp file for this header MyTemplate.cpp
I can include the code for all member-functions of Mytemplate class without problems
for example :
template <class Type>
int MyStack<Type>::public_func_of_stackt(void) /*this works perfect*/
{implementation goes here ...;}
but when i am trying to write the implementation of member-functions of entire class (iterator class) the problem starts
template <class Type>
bool MyStackt<Type>::iterator somefunc(param1,param2.....)
{ return current ==rhs.current; }
the question sirs is:
how I can include my code for the member-functions of class iterator inside the Mytemplate.cpp file ?? how should i write that using that external::entire or other specific notation ?
other question :
how can i write (in Mytemplate.cpp file) the implementation for a friend function of class MyStackt ??
update#1 : thank you Veritas
but i also need to know how to define some public function of class MyStackt
if that function is returning iterator type (so it is returning an object of the entire class)
the definition will look something like that
template <class Type>
iterator Stackt<Type>::begin()
{ return *this; } /*this function did not work*/
maybe I need to use some specific notation 4 that ? what if I had a multiple nested classes
waiting for the answer from experts
thank you in advance !
You forgot the scope resolution operator when defining somefunc. The definition should be:
template <class Type>
bool MyStackt<Type>::iterator::somefunc(param1,param2.....)
{
return current == rhs.current;
}
As for the friend function, you define it like any other global function.
To your edit:
The iterator class belongs to the MyStackt's scope so whenever you need to mention it out of MyStackt you need to use the scope operator. As for your question I am not sure what you are trying to do. *this returns the instantiated object which is of type MyStackt.
Also be careful! If you want to seperate your definitions do so using .inl files or similar , not in a cpp file.

CRTP, forward declarations and templates in cpp files

I'm using the CRTP pattern to create an interface, which other classes will derive from.
In the interface I forward declare a structure (important because I don't want to drag other stuff in the interface), but I include its definition in the cpp file which defines the interface.
Interface.h
#ifndef INTERFACE_H_INCLUDED
#define INTERFACE_H_INCLUDED
// forward declaration
class ForwardDecl;
template <class Derived>
class Interface
{
public:
ForwardDecl interfaceMethod();
};
#endif // INTERFACE_H_INCLUDED
ForwardDecl.h
#ifndef FORWARDDECL_H_INCLUDED
#define FORWARDDECL_H_INCLUDED
struct ForwardDecl
{
ForwardDecl(int i):internal(i)
{}
int internal;
};
#endif // FORWARDDECL_H_INCLUDED
Interface.cpp
#include "Interface.h"
#include "ForwardDecl.h"
template<class Derived>
ForwardDecl Interface<Derived>::interfaceMethod()
{
return static_cast<Derived *>(this)->implementation_func();
}
And this is the implementation which implements the interface
Implementation.h
#ifndef IMPLEMENTATION_H_INCLUDED
#define IMPLEMENTATION_H_INCLUDED
#include "Interface.h"
class ForwardDecl;
class Implementation: public Interface<Implementation>
{
friend class Interface<Implementation>;
private:
ForwardDecl implementation_func();
};
#endif // IMPLEMENTATION_H_INCLUDED
Implementation.cpp
#include "Implementation.h"
#include "ForwardDecl.h"
#include <iostream>
struct ForwardDecl Implementation::implementation_func()
{
ForwardDecl fd(42);
std::cout << fd.internal << std::endl;
return fd;
}
And the main file
#include <iostream>
#include "Implementation.h"
#include "ForwardDecl.h"
using namespace std;
int main()
{
Implementation impl;
ForwardDecl fd = impl.interfaceMethod();
cout << fd.internal << endl;
return 0;
}
I get linking errors on both VS and GCC.
Any workaround? Thank you.
There is a flaw in your very approach: You have a public function returning a ForwardDecl instance, so every client wanting to use this function also must include the according definition of that type, which implies you can make that type public from the beginning. This includes making the function definition inline, which will fix your linker problems.
However, if you really want to hide the content of that structure and you are sure clients don't need it directly, you can declare it and then pass around references to such a structure (or pointers, but raw pointers are evil albeit not in the same league of evil as #macros). In that case, I would still make the function definition inline.
If you really, really want to not make the function inline, you can also explicitly instantiate the function template for the types that you need. You would add at the end of the template's .cpp file something like template class Interface<int>; (I don't remember the exact syntax so take that with a few flakes of fleur de sel, check out the C++ FAQ at parashift.com for more info). This makes the template a little less universal though, as it requires adjustments for any type that you want to use it with, but it can be an approach in some corner cases.
The definitions of function templates and member functions of class templates need to be visible in all translation units that instantiate those templates. That is, you shouldn't put template definitions in a .cpp file, which means you need to move the contents of Interface.cpp up into Interface.h.

How to make an inner class without putting the definition of inner class to parent class?

I'll write an header file,and it's very long.Since it will be too complicated,i don't want to put inner class definition in root class.I mean how can i make a class inner without writing it in root class.
class outer
{
}
class inner
{
}
If i can use like that, The header file will be clearer i think.
Like this:
// foo.hpp
class Foo
{
public:
class Inner;
Foo();
void bar();
Inner zoo();
};
// foo_inner.hpp
#include "foo.hpp"
class Foo::Inner
{
void func();
};
Then, in the implementation:
#include "foo.hpp"
#include "foo_inner.hpp"
void Foo::bar() { /* ... */ }
void Foo::Inner::func() { /* ... */ }
Note that you can use the incomplete type Foo::Inner inside the class definition of Foo (i.e. in foo.hpp) subject to the usual restrictions for incomplete types, e.g. Inner may appear as a function return type, function argument, reference, or pointer. As long as the member function implementations for the class Foo can see the class definition of Foo::Inner (by including foo_inner.hpp), all is well.
You can specify 'outer' as "public class outer", and put both its definition and the "inner" definition into a "class.java" file, and code in outer can instantiate inner just as if inner was in a different source file. It is not clear that is what you're after, because you have not explained why you want an "inner" class.