I'm trying to understand some C++ code. I'm an experienced Java programmer trying to learn C++. I've already read some exhaustive articles on templates, but no one of them answered me what does the following template specification mean.
template<
template<template<class> class, class> class VisualOdometryTT,
template<class> class NodeBuilderTT,
class PoseGraphT>
class VORosInterface{ ... };
The part I don't understand is template<class> where I think some type specification is missing. But the code compiles without problems.
Using NodeBuilderTT as an example because it's easier:
NodeBuilderTT is a template parameter that is itself a template having one parameter -- let's call that Z.
You could have chosen to formally name Z and the code would compile just the same:
template<class Z> class NodeBuilderTT
So far this is quite similar to declaring function arguments:
void foo(int x) {} // works
void foo(int) {} // also works
However, with the functions you would typically use the name x inside the function body. With templates you cannot use Z in the definition of VORosInterface, so there is absolutely no point in naming it and it is idiomatic to write
template<class> class NodeBuilderTT
My thanks to K-ballo for helping set the record straight here.
Related
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.
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.
I've searched through the web an didn't find any explanation why the following happens.
For example, there is a template class Enclosing with a nested class Nested.
In Enclosing class, there is a method that should create an instance of the Nested class and use it's fields and methods.
In the following code, there is a model of how I'm trying to do it:
template<typename T, typename S>
class Enclosing{
public:
class Nested;
Nested foo();
};
template<typename T, typename S>
class Enclosing<T,S>::Nested{
public:
T field;
void some_method();
friend class Enclosing; // instead of this line I also tried:
// friend class Enclosing<T,S>
// and it didn't work either
};
template<typename T, typename S>
typename Enclosing<T,S>::Nested Enclosing<T,S>::foo (){
Nested nes;
nes.some_method; // the problem appears here
return enc;
}
The problem is:
When I'm writing nes.some_method, none of the environments I tried (VS2010, eclipse), after I type "nes.", doesn't propose me any options. I seems like "nes" is not an instanse of the class at all.
How to access methods and fields of the nested class from enclosing template class?
This line:
Nested nes();
Does not create an object of type nes, but rather declares a function which takes no arguments and returns an object of type Nested. I suspect this to be the source of your problem, not the friend declaration. Just remove the pair of parentheses after nes:
Nested nes;
Alternatively, in C++11 you may do:
Nested nes{};
EDIT:
After fixing the above error, it still seems your program does not compile & link correctly - doubtfully because of the same problem. What I can tell from your code is that a definition of the some_method() member function is still missing, and that may be a reason for the linker to refuse creating the executable for your program.
Here:
Nested nes();
You're not calling the default constructor of Nested but rather declaring a function named nes that takes 0 arguments and returns by value an instance of the Nested class. This is referred to as the Most Vexing Parse. Remove the parameters to get the code to function properly.
Here is a working demo.
We have following class definition
template<typename T>
class Klass {...}
and we also have below two instantiations
Klass<int> i;
Klass<double> d;
how many copies of Klass' methods are generated by the C++ compiler?
Can somebody explain it? Thanks!
Klass isn't a type, so it doesn't make sense to talk of Klass's methods. Kalss<int> is a type with it's own methods, and so is Klass<double>. In your example there would be one set of methods for each type.
Edit in real life, it isn't as simple as that. The question of the actual existence of the methods also depends on other factors, see #KerrekSB's answer to this question.
Each template instance is an entirely separate, distinct and independent type of its own. However, the code for class template member functions is only generated if the member function is actually used for a given template instantiation (unless you instantiate the template explicitly for some set of parameters). Among other things, this means that if some class template member function's body doesn't actually make sense for a given template parameter, then you can still use the overall template as long as you don't invoke that member function, since the code for the member function will never get compiled.
Also bear in mind that templates can be specialized:
template <typename T> struct Foo {
int bar;
void chi();
};
template <> struct Foo<int> {
double bar(bool, char) const;
typedef std::vector<bool> chi;
bool y;
};
As you can see, there's a lot you cannot just tell from a template itself until you see which actual instantiations you'll be talking about.
I have a class MyClass which is templated on typename T. But inside, I want a method which is templated on another type TT (which is unrelated to T).
After reading/tinkering, I found the following notation:
template <typename T>
class MyClass
{
public :
template<typename TT>
void MyMethod(const TT & param) ;
} ;
For stylistic reasons (I like to have my templated class declaration in one header file, and the method definitions in another header file), I won't define the method inside the class declaration. So, I have to write it as:
template <typename T> // this is the type of the class
template <typename TT> // this is the type of the method
void MyClass<T>::MyMethod(const TT & param)
{
// etc.
}
I knew I had to "declare" the typenames used in the method, but didn't know how exactly, and found through trials and errors.
The code above compiles on Visual C++ 2008, but: Is this the correct way to have a method templated on TT inside a class templated on T?
As a bonus: Are there hidden problems/surprises/constraints behind this kind of code? (I guess the specializations can be quite amusing to write)
This is indeed the correct way of doing what you want to do, and it will work on every decent C++ compiler. I tested it on gcc4.4 and the latest clang release.
There are problems/surprises/constraints behind any kind of code.
The major issue you could eventually run in with this code is that you can't make a templated function virtual, so if you want to get polymorphism at the class level for your templated function, you're off implementing it with an external function.
I think It's OK to do that. Take a look for example at std::vector implementation. You have class vector, which has a few template parameters (most notably an element type), and inside, one of its constructors is declared in similar way as your method. It has InputIterator as a template parameter. So I think that this is not so uncommon practice.