Forward declaration of a template class c++ - c++

I saw similar examples, but didn't understand them fully so please don't mark this as duplicate straight away.
I think there's a simple solution for my problem, and I'm only learning C++.
I want to use:
template<class T, std::size_t N>
class arnas_array {
//a copy of std:array functionality, basically, here.
};
in another class header, another file, example:
class options_databaze {
public:
struct options_to_save{
arnas_array<char, 123> option_name;
//char option_name[103];
int * option_value_pointer;
};
};
And I can't get it to work.
Forward declaration like this won't work:
template<class T, std::size_t N>
class arnas_array;
I don't know much about this problem, first time I'm stuck here, any examples are gold.
error C2079: 'options_databaze::options_to_save::option_name' uses undefined class 'arnas_array<char,123>'

The question has nothing to do with templates. In C++ a class type T must be complete, in particular, if a non-static class data member of type T is declared (see 3.2/5 (One definition rule) section of the standard, or read more human-readable version here).
"Must be complete" means that the definition of the class T should precede the definition of the corresponding data member. A common way to achieve this, as was pointed out by Cameron in the comments, is to put a definition in a header file and include that header everywhere it's needed - just the same way as you do when you include standard headers such as <vector>, <map> and so on.

Related

C++ conditional template class definition of member function

Given the following class forward declaration in a header file:
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
class context
{
public:
context();
// ....
private:
// ....
T data;
}
How can I define the constructor (or any other member function) in the cpp file? Tried everything I can think of but nothing matched....
This other question was brought to my attention Why can templates only be implemented in the header file? and I have successfully used the methodology suggested in the accepted answer in multiple places in my project, however I can not find a way to represent the second template parameter in any way... that question does not provide enough information to do that. The problem is here the second template parameter makes that either incompatible with the suggested way there or I just could not find the appropriate syntax to represent it, if my class would have just the first parameter it would answer it...
P.S. Sorry if this is a duplicate, I really tried to find a similar question just could not find the appropriate terminology to find a match.
To supply an out of class definition, the template parameter list must match.
template<typename T, std::enable_if_t<std::is_integral_v<T>, int> N>
context<T, N>::context() {
}
The parameter type is std::enable_if_t<std::is_integral_v<T>, int> in the class template definition. And that's exactly what needs to be the type of the parameter in the out of class definition.
As an aside, I don't see a benefit for the check being where it is currently. Unlike function templates, where this may affect overload resolution, class templates don't benefit much if at all from the mechanism. IMO it would be preferable to simply add a static assertion to the class template declaration
template<typename T>
class context {
static_assert(std::is_integral_v<T>, "Must be initialized with an integral type");
// ...
};
Then the out of class member declarations become much more straight forward. And error messages about bad template arguments are much more readable.

Will C++17 allow forward declaration of nested classes?

Not sure where to ask (feel free to close this if it is an inappropriate question) but I have not found anything on this specifically in C++17 proposals, neither this or this mentions it when dealing with the nested namespace addition to C++.
So currently this is the only option:
class A
{
public:
class B; //forward-declared INSIDE class/namespace
};
class A::B //defined outside
{
};
Will this be possible in C++17?
class A::B; //forward declared NESTED outside of parent class/namespace
class C
{
A::B *b;
};
and then either this (1) (as seems to be the proposal of nested namepsace definitions)
class A::B //definition of A::B without defining A
{
};
or this (2)
class A
{
public:
class A::B
{
};
};
or this [3]
class A
{
public:
class B;
};
class A::B
{
};
I suspect the definition of A::B without defining A first might not work though (although the proposal seems to allow it).
There's a proposal on the issue titled Forward declarations of nested classes P0289R0. However as you can see from the last Trip Report: C++ Standards Meeting in Jacksonville, February 2016, this proposal was pendent to proposals for which further work is encouraged. I'm quoting the verdict of the committee (Emphasis Mine):
This would allow things like X::A* to appear in a header without
requiring a definition for X to also appear in the header
(forward-declarations of X and X::A will be sufficient). EWG found the
use case compelling, because currently a lot of class definitions to
appear in headers only because interfaces defined in the header use
pointers or references to nested classes of the type. Several details
still need to be worked out. (For example, what happens if a
definition of X does not appear in any other translation unit (TU)?
What happens if a definition of X appears in another TU, but does not
define a nested class A? What happens if it does define a nested class
A, but it’s private? The answer to some or all of these may have to be
“ill-formed, no diagnostic required”, because diagnosing errors of
this sort would require significant linker support.)
IMHO lacking the ability to do forward deceleration of classes is a major hole in C++ language definition, which results in people using void* where a forward reference would be more safe.
Here is a workaround using namespaces:
Flatten the class structure you need to pre-declare
Use namespaces to separate the code
Do the forward deceleration using the namespaces
namespace ns1 {
namespace ns2 {
typedef class C * cptr_t; // declare both class and a pointer type
}}
ns1::ns2::C *cp; // use forward deceleration of the class
ns1::ns2::cptr_t cp; // use the typedef
This workaround does not solve the problem properly but may help in some situations.

The difference between #include .h and just stating class A; in C++ [duplicate]

This question already has answers here:
When can I use a forward declaration?
(13 answers)
Closed 8 years ago.
I'm analying an Operating Systems project for school and came across this header file:
//kernelev.h
#ifndef _KERNELEV_H
#define _EVENT_H_
typedef unsigned char IVTNo;
class Thread;
class PCB;
class KernelSem;
class KernelEv {
public:
KernelEv (IVTNo ivtNo);
~KernelEv();
int wait(int MaxTimeToWait);
void signal();
[...]
Now, when writing the complete definitions of these methods (KernelEv, ~KernelEv, wait and signal), they used the attributes of the classes Thread, PCB and KernelSem. What would be the difference between generally introducing for instance #include Thread.h; #include KernelSem.h; and just declaring the classes like this: class Thread; Are there differences in data access rights? Or it's somehow completely different?
Thanks for your help, I hope my question is clear enough.
First, note that if you only introduce the classes, you won't be able to use the methods;
class Thread;
Thread x; // compile error: size of x unknown
Thread* x; // this is ok
// set x to some valid thread, maybe as a parameter
x->signal(); // compile error
But it makes no difference whether your declarations are in a header or included in your file. That is, you could replace the include line with a copy of the header and everything would work perfectly fine (every line in the above example would be valid). There are many reasons not to, however. Ease of maintenance would be the top issue, along with readability and modularity. It would also be less applicable to compiler caching (so would generally take longer to compile)
If you only have a declaration class A; and not the full class definition, then the type is said to be incomplete. This can be used in limited ways; you can do things that only need knowledge that the class exists, for example:
Declare a pointer or reference to it;
Declare a function using it as a parameter or return type;
Declare (but not define) an external variable of that type.
You can't do anything that requires knowledge of the class members, size, or other details given by the definition, for example:
Define a variable of that type;
Define a function using it;
Access any members or nested declarations;
Inherit from it;
Apply sizeof to it.
If I am not wrong, you are asking about Declaration vs Definition. They are different but related.
I forward you to this two posts googled as "c++ declaration definition", since they will explain much better than me :)
What is the difference between a definition and a declaration?
http://www.cprogramming.com/declare_vs_define.html
Just comment that your class A; is a declaration, while the includes Thread.h surely will have plenty definitions inside (and maybe declarations too).
--------------------- edit:
About forward declarations as commented by #Dave bellow:
class B ; // needed declaration
class A {
B field ;
} ;
class B {
A field ;
};

template class with STL container member

I'm writing a template class that uses a std::multimap as a member, and getting compile errors.
LocTree.h:
#pragma once
#include <map>
template <class Loc, class T>
class LocTree
{
public :
typedef std::multimap<typename Loc, typename T> TreeType;
LocTree( void );
~LocTree( void ) { };
private :
TreeType db;
};
LocTree.cpp:
#include "StdAfx.h"
#include "LocTree.h"
LocTree< class Loc, class T>::LocTree()
{
}
The compile error (from VC2005) :
Error 1 error C2079: 'std::pair<_Ty1,_Ty2>::first' uses undefined class 'Loc' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 53
Error 2 error C2079: 'std::pair<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 8\vc\include\utility 54
I know I could put the function definitions in the .h but I'm hoping to keep them separate, if it's legal to do so. How do I fix this (probably newbie) problem?
Your constructor definition should be:
template<class Loc, class T>
LocTree<Loc,T>::LocTree()
{
}
Also, hoping to keep them separate... - don't - you're wasting your time. The only way to keep them separate is to have a definition in a different header which you also include. So, technically, they are separate, but the implementation is still visible.
Two points. The first is: what is:
typedef std::multimap<typename Loc, typename T> TreeType;
supposed to mean? I don't see what the typename are doing in there; I
think you just want:
typedef std::multimap<Loc, T> TreeType;
Second, when defining a member function of a class template outside of the
class, the syntax is:
template <typename Loc, typename T>
LocTree<Loc, T>::LocTree()
{
}
In other words, you have to repeat the template<...> clause. (Whether
you use typename or class in the <...> is indifferent. Since it
doesn't have to be a class, Most people I know prefer typename, since
this corresponds closer to what is meant.)
As for keeping the implementation separate: templates in C++ are
somewhat broken in this respect. You can't avoid the compiler
dependency. You still do want to keep the implementation separate from
the definition, however. The usual technique is to put the template
implementation in a separate file (.tcc, for example), and include
this from the header.
Keeping the implementation of a template separate is not a trivial thing to do.
In general it cannot be done. That is, it cannot be done where the templated parameters may be "anything".
For a specific limited subset of templated parameters it is possible to do, for example if you have a template like:
template< bool B > class Foo;
You can then specify:
extern template class Foo<true>;
extern template class Foo<false>;
and this is called "instantiating" the templates, and specifying to the compiler that there are implementations for values true and false, implemented elsewhere.
This can also be done where the templated parameters are types and are limited to a specific subset.
Within the compilation unit you then define the template implementations and then instantiate the templates once again using the same as above but without the word "extern".
I have done this in production code in a case where you are creating a member function to set a parameter value for a database stored-procedure call where only a very limited subset of parameter types are permitted. If your types are a very limited subset then go ahead and do the same if this helps decouple the code and hide a lot of implementation detail (in the case where the implementation is then done in a database, it is well worth doing).
There is an "in-between" ground where you provide the implementation in another header, often I have seen _i.h or similar for this convention and then you instantiate the templates in ones, including this header only when necessary. Thus if you create a class Foo then in the header use the "extern" declaration for my foo class in Foo.h and in Foo.cpp, #include the _i.h file for the implementation and the instantiation.
As for the syntax, in the template implementation file use:
template<class Loc, class T>
LocTree<Loc,T>::method(...)
{
...
}

Template specialization of a single method from a templated class

Always considering that the following header, containing my templated class, is included in at least two .CPP files, this code compiles correctly:
template <class T>
class TClass
{
public:
void doSomething(std::vector<T> * v);
};
template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
// Do something with a vector of a generic T
}
template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
// Do something with a vector of int's
}
But note the inline in the specialization method. It is required to avoid a linker error (in VS2008 is LNK2005) due to the method being defined more then once. I understand this because AFAIK a full template specialization is the same as a simple method definition.
So, how do I remove that inline? The code should not be duplicated in every use of it. I've searched Google, read some questions here in SO and tried many of the suggested solutions but none successfully built (at least not in VS 2008).
Thanks!
As with simple functions you can use declaration and implementation.
Put in your header declaration:
template <>
void TClass<int>::doSomething(std::vector<int> * v);
and put implementation into one of your cpp-files:
template <>
void TClass<int>::doSomething(std::vector<int> * v) {
// Do somtehing with a vector of int's
}
Don't forget to remove inline (I forgot and thought this solution will not work :) ).
Checked on VC++2005
You need to move specialization definition to CPP file.
Specialization of member function of template class is allowed even if function is not declared as template.
There is no reason to remove the keyword inline.
It does not change the meaning of the code in anyway.
If you want to remove the inline for whatever reason the solution of maxim1000 is perfectly valid.
In your comment, though, it seems you believe that the inline keyword means that the function with all his contents gets always inlined but AFAIK that is actually very much dependent on your compiler optimization.
Quoting from the C++ FAQ
There are several ways to designate that a function is inline, some of
which involve the inline keyword, others do not. No matter how you
designate a function as inline, it is a request that the compiler is
allowed to ignore: the compiler might inline-expand some, all, or none
of the places where you call a function designated as inline. (Don’t
get discouraged if that seems hopelessly vague. The flexibility of the
above is actually a huge advantage: it lets the compiler treat large
functions differently from small ones, plus it lets the compiler
generate code that is easy to debug if you select the right compiler
options.)
So, unless you know that that function will actually bloat your executable or unless you want to remove it from the template definition header for other reasons, you can actually leave it where it is without any harm
This is a little OT, but I thought I'd leave this here in case it helps someone else. I was googling about template specialization which led me here, and while #maxim1000's answer is correct and ultimately helped me figure my problems out, I didn't think it was abundantly clear.
My situation is a little different (but similar enough to leave this answer I think) than the OP's. Basically, I'm using a third party library with all different kinds of classes that define "status types". The heart of these types are simply enums, but the classes all inherit from a common (abstract) parent and provide different utility functions, such as operator overloading and a static toString(enum type) function. Each status enum is different from one another and unrelated. For example, one enum has the fields NORMAL, DEGRADED, INOPERABLE, another has AVAILBLE, PENDING, MISSING, etc. My software is in charge of managing different types of statuses for different components. It came about that I wanted to utilize the toString functions for these enum classes, but since they're abstract I couldn't instantiate them directly. I could have extended each class I wanted to use, but ultimately I decided to create a template class, where the typename would be whatever concrete status enum I cared about. Probably some debate can be had about that decision, but I felt like that was a lot less work than extending each abstract enum class with a custom one of my own and implementing the abstract functions. And of course in my code, I just wanted to be able to call .toString(enum type) and have it print the string representation of that enum. Since all the enums were entirely unrelated, they each had their own toString functions that (after some research I learned) had to be called using template specialization. That led me here. Below is an MCVE of what I had to do in order to make this work correctly. And actually my solution was a bit different than #maxim1000's.
This is a (greatly simplified) header file for the enums. In reality, each enum class was defined in it's own file. This file represents the header files that are supplied to me as part of the library I am using:
// file enums.h
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
adding this line just to separate the next file into a different code block:
// file TemplateExample.h
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
// this is the function I was most concerned about. Unlike #maxim1000's
// answer where (s)he declared it outside the class with full template
// parameters, I was able to keep mine declared in the class just like
// this
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
next file
// file TemplateExample.cpp
#include <string>
#include "enums.h"
#include "TemplateExample.h"
// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
next file
// and finally, main.cpp
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
and this outputs:
BEARS1
TIGERS3
No clue if this is the ideal solution to solve my problem, but it worked for me. Now, no matter how many enumeration types I end up using, all I have to do is add a few lines for the toString method in the .cpp file, and I can use the libraries already-defined toString method without implementing it myself and without extending each enum class I want to use.
I'd like to add that there is still a good reason to keep the inline keyword there if you intend to leave also the specialization in the header file.
"Intuitively, when you fully specialize something, it doesn't depend on a template parameter any more -- so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule..."
Reference: https://stackoverflow.com/a/4445772/1294184