C++ Template - No viable conversion error - c++

I'm now dealing with template in c++ with PCL (Point Cloud Library) and I encountered something that I'm not able to solve (I searched before on the internet and on Stack)
I have a template class called Features.
my hpp file:
#ifndef KeyFeatures_hpp
#define KeyFeatures_hpp
// Declarations and includes
typedef pcl::PointXYZRGB PointTypeRGB;
template<typename FeatureType>
class Features {
public:
Features(const int typeDescriptor);
void setDescriptorExtractor(typename pcl::Feature<PointTypeRGB, FeatureType>::Ptr extractor);
private:
typename pcl::Feature<PointTypeRGB, FeatureType>::Ptr m_descriptor_extractor;
};
#endif /* Features_hpp */
In the cpp file I have a constructor which will checks what kind of type is it and then perform some action.
template <typename FeatureType>
Features<FeatureType>::Features(const int type){
//Some code
if (type == DESCRIPTOR_SHOT){
pcl::SHOTEstimationOMP<PointTypeRGB, pcl::Normal, pcl::SHOT352>* shot = new pcl::SHOTEstimationOMP<PointTypeRGB, pcl::Normal, pcl::SHOT352>;
shot->setRadiusSearch (0.02f);
pcl::Feature<PointTypeRGB, pcl::SHOT352>::Ptr descriptor_extractor (shot);
descriptor_extractor->setSearchMethod (pcl::search::Search<PointTypeRGB>::Ptr (new pcl::search::KdTree<PointTypeRGB>));
this->m_descriptor_extractor = descriptor_extractor;//ERROR
setDescriptorExtractor(descriptor_extractor);//ERROR
// Some code
}
The error appeared in the last two lines when I try without success to fill in my variable member.
Each time I have the following error x 10 (corresponding to my 10 kind of type)
error: no matching conversion for functional-style cast from 'const shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::SHOT352> >'
to 'this_type' (aka 'shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::ShapeContext1980> >')
However at the end of my cpp file I put all my template class. For example:
template class Features<pcl::SHOT352>;
In my main function I called this class by using:
Features<pcl::SHOT352> feature_SHOT(type);
It seems that it's not able to perform the conversion..
Can someone might be able to help me ?
Thank

Apparently you are instantiating Features<pcl::ShapeContext1980> so its m_descriptor_extractor has the type pcl::Feature<pcl::PointXYZRGB, pcl::ShapeContext1980>::Ptr which is shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::ShapeContext1980>>.
But inside the constructor you are still using pcl::Feature<pcl::PointXYZRGB, pcl::SHOT352>::Ptr, that is shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::SHOT352>> - a totally different type.
And as a side note, you generally don't implement templates in .cpp files.

Firstly, the official term is a "class template" - a template for creating classes.
You appear to have created a class called Features<pcl::ShapeContext1980>.
This has m_descriptor_extractor of type shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::ShapeContext1980> >
You are trying to assign a shared_ptr<pcl::Feature<pcl::PointXYZRGB, pcl::SHOT352>> to it.
They are completely unrelated types, so it fails at compile time.

Related

"Expected a type specifier" error when creating an object of a class inside another class declaration

I have a class called scratch and have used scratch.h to declare it.
Now I have another class called scratch2 under scratch2.h and want to create an object of scratch as a shared pointer.
This is the syntax I used inside scratch2 class declartion:
std::shared_ptr<scratch> newObject(new scratch());
But I am getting this error: Error: Expected type specifier
So I tried this instead:
std::shared_ptr<scratch> newObject2 = std::make_shared<scratch>();
which works fine. Can anyone please tell me why the first one isn't working?
My scratch.h code:
#ifndef _SCRATCH_
#define _SCRATCH_
#include <iostream>
class scratch {
private:
int _a;
float _b;
std::string _s;
public:
scratch();
scratch(int a, float b, std::string n);
~scratch();
};
#endif
and my scratch2.h:
#ifndef _SCRATCH_2_
#define _SCRATCH_2_
#include "scratch.h"
#include <memory>
class scratch2 {
std::shared_ptr<scratch> newObject(new scratch()); // Expected a type specifier error occurs here
std::shared_ptr<scratch> newObject2 = std::make_shared<scratch>(); // works fine here
};
#endif
Because in the context of declaring class members:
std::shared_ptr<scratch> newObject(new scratch());
This initially looks to the compiler as a class method declaration. C++'s syntax is very complicated. You can look at the entire declaration and understand what it's trying to do, but the compiler is parsing keywords one keyword at a time, and sees this:
type name( ...
inside a class declaration, and this starts to look like a class method declaration, and that's what the compiler tried to parse, and failed.
The formal specification of the C++ language spills a lot of ink on the subject of how things should be declared, mindful of the current state of compiler technology.
You need to work with the compiler, and use an alternate syntax that's unambiguous:
std::shared_ptr<scratch> newObject = std::shared_ptr<scratch>(new scratch());
Verified with gcc 5.3
Inside of a class definition, there are only two ways you're allowed to initialize your members. You can use = and you can use {}. You are not allowed to use ():
struct foo {
int x = 4; // OK
int y{7}; // OK
int z(12); // error
};
Admittedly, the compiler error in this case is extremely unhelpful.

Why can't I pass typedef or enum in Arduino?

The following sketch to fails to compile in the Arduino environment.
Given that typedefs can be used within Arduino software, is Automatic Prototype Generation the underlying mechanism that causes the failure? If so, what is it and why isn't Arduino providing a lightweight wrapper around C++?
#define PRODUCE_WACKY_COMPILETIME_ERROR
typedef int MyMeaningfulType;
#ifndef PRODUCE_WACKY_COMPILETIME_ERROR
void myFunc(MyMeaningfulType myParam);
#endif
void myFunc(MyMeaningfulType myParam)
{
myFunc(10);
}
void setup() {}
void loop() {}
For the benefit of the search engines, the errors reported are:
error: variable or field 'myFunc' declared void
error: 'MyMeaningfulType' was not declared in this scope
Please refer to http://arduino.cc/en/Hacking/BuildProcess the specific quote is:
This means that if you want to use a custom type as a function argument, you should declare it within a separate header file.
This page does a good job of explaining how the Arduino Language is different from C/C++ in how it works/pre-processes files.
They are attempting to create prototypes for every function they find. Unfortunately, if you define a typedef in the file before the function, and use that in a function definition, the place they put the function prototype does not see it, and this generates a syntax error.
If you use the 'struct * ' syntax instead in those function definitions, you benefit from C's 'opaque type' facility, in which you can use a struct definition without having it be declared beforehand. So, build the typedef, use it, but use the struct definition in any functions that use the typedef in arguments.
typedef struct mytype_ {
int f1;
} mytype_t;
void myfunc(struct mytype_ * xxx) {
xxx->f1 = 1;
}

Using boost::iostreams::mapped_file_source with wide character strings

If I instantiate a mapped_file_source (boost 1.46.1 ) with a narrow character string as in the following I don't have a problem:
boost::iostreams::mapped_file_source m_file_( "testfile.txt" );
However if I try to use a wide string:
boost::iostreams::mapped_file_source m_file_( L"testfile.txt" );
I get the following compiler error in VC2010 SP1:
P:\libs\boost_1_46_1\boost/iostreams/device/mapped_file.hpp(128): error C2248: 'boost::iostreams::detail::path::path' : cannot access private member declared in class 'boost::iostreams::detail::path'
P:\libs\boost_1_46_1\boost/iostreams/detail/path.hpp(111) : see declaration of 'boost::iostreams::detail::path::path'>
P:\libs\boost_1_46_1\boost/iostreams/detail/path.hpp(37) : see declaration of 'boost::iostreams::detail::path'
If I instead try to pass the constructor a boost::filesystem::path I get the following error:
P:\libs\boost_1_46_1\boost/iostreams/device/mapped_file.hpp(128): error C2664: 'boost::iostreams::detail::path::path(const std::string &)' : cannot convert parameter 1 from 'const boost::filesystem3::path' to 'const std::string &'
Reason: cannot convert from 'const boost::filesystem3::path' to 'const std::string'
I feel like I'm missing something obvious, but I'm just running around in circles trying to figure out what the compiler is trying to tell me, but I'm just getting lost. That palm to forehead moment is just not happening.. What is it that I am doing incorrectly?
The constructor defined in mapped_file.hpp looks like the following:
// Constructor taking a parameters object
template<typename Path>
explicit mapped_file_source(const basic_mapped_file_params<Path>& p);
The basic_mapped_file_params class constructors look like this:
// Construction from a Path
explicit basic_mapped_file_params(const Path& p) : path(p) { }
// Construction from a path of a different type
template<typename PathT>
explicit basic_mapped_file_params(const PathT& p) : path(p) { }
Where the template class is defined as:
// This template allows Boost.Filesystem paths to be specified when creating or
// reopening a memory mapped file, without creating a dependence on
// Boost.Filesystem. Possible values of Path include std::string,
// boost::filesystem::path, boost::filesystem::wpath,
// and boost::iostreams::detail::path (used to store either a std::string or a
// std::wstring).
template<typename Path>
struct basic_mapped_file_params
: detail::mapped_file_params_base
{
There is some additional help in the header that says:
// For wide paths, instantiate basic_mapped_file_params
// with boost::filesystem::wpath
If I take this approach with:
boost::iostreams::basic_mapped_file_params<boost::filesystem::wpath> _tmp(L"test.txt");
boost::iostreams::mapped_file_source m_file_( _tmp );
I get the same C2664 error mentioned above..
I know the compiler is telling me what the problem is, but looking at the header source and the comments leads me to believe that what I'm trying to accomplish is supported, it's just my approach that is incorrect. Am I misinterpreting what the header file is telling me? I know there is probably a good lesson about template instantiation and explicit/implicit conversion in here somewhere.
Interestingly enough, upgrading my boost install to 1.47.0 seems to cleared up C2664 error but I'm still getting the C2248 error about access to the private member.
With boost 1.48 I can do something like this.
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <iostream>
int main()
{
boost::filesystem::path p(L"b.cpp");
boost::iostreams::mapped_file file(p); // or mapped_file_source
std::cout << file.data() << std::endl;
}
or you can do this with mapped_file_params(used create new file)
boost::filesystem::path p(L"aa");
basic_mapped_file_params<boost::filesystem::path> param; // template param
param.path = p;
param.new_file_size = 1024;
It's telling you that boost::iostreams::mapped_file_source's constructor does not take a wchar_t*, nor does it take a boost::filesystem::path. It only takes std::string, or types convertible to std::string. Or, to put it another way, you can't use UTF-16 paths with this object.
It looks like the documentation for mapped_file is pretty old and does not reflect what is in the header or in the header comments. In order to instantiate a boost::iostreams:mapped_file_source object with a wide character string you need to explicity pass in the boost::iostreams::detail::path like this:
boost::iostreams::mapped_file_source m_file_( boost::iostreams::detail::path(boost::filesystem::path(L"testfile.txt")) );
I was able to get this to compile by stepping thought the error messages and determining how the template classes were being instantiated and finally saw that boost::iostreams::detail::path had a private constructor that took a &std::wstring as a parameter which is where the code was failing to compile.

Splitting templated C++ classes into .hpp/.cpp files--is it possible?

I am getting errors trying to compile a C++ template class which is split between a .hpp and .cpp file:
$ g++ -c -o main.o main.cpp
$ g++ -c -o stack.o stack.cpp
$ g++ -o main main.o stack.o
main.o: In function `main':
main.cpp:(.text+0xe): undefined reference to 'stack<int>::stack()'
main.cpp:(.text+0x1c): undefined reference to 'stack<int>::~stack()'
collect2: ld returned 1 exit status
make: *** [program] Error 1
Here is my code:
stack.hpp:
#ifndef _STACK_HPP
#define _STACK_HPP
template <typename Type>
class stack {
public:
stack();
~stack();
};
#endif
stack.cpp:
#include <iostream>
#include "stack.hpp"
template <typename Type> stack<Type>::stack() {
std::cerr << "Hello, stack " << this << "!" << std::endl;
}
template <typename Type> stack<Type>::~stack() {
std::cerr << "Goodbye, stack " << this << "." << std::endl;
}
main.cpp:
#include "stack.hpp"
int main() {
stack<int> s;
return 0;
}
ld is of course correct: the symbols aren't in stack.o.
The answer to this question does not help, as I'm already doing as it says.
This one might help, but I don't want to move every single method into the .hpp file—I shouldn't have to, should I?
Is the only reasonable solution to move everything in the .cpp file to the .hpp file, and simply include everything, rather than link in as a standalone object file? That seems awfully ugly! In that case, I might as well revert to my previous state and rename stack.cpp to stack.hpp and be done with it.
It is not possible to write the implementation of a template class in a separate cpp file and compile. All the ways to do so, if anyone claims, are workarounds to mimic the usage of separate cpp file but practically if you intend to write a template class library and distribute it with header and lib files to hide the implementation, it is simply not possible.
To know why, let us look at the compilation process. The header files are never compiled. They are only preprocessed. The preprocessed code is then clubbed with the cpp file which is actually compiled. Now if the compiler has to generate the appropriate memory layout for the object it needs to know the data type of the template class.
Actually it must be understood that template class is not a class at all but a template for a class the declaration and definition of which is generated by the compiler at compile time after getting the information of the data type from the argument. As long as the memory layout cannot be created, the instructions for the method definition cannot be generated. Remember the first argument of the class method is the 'this' operator. All class methods are converted into individual methods with name mangling and the first parameter as the object which it operates on. The 'this' argument is which actually tells about size of the object which incase of template class is unavailable for the compiler unless the user instantiates the object with a valid type argument. In this case if you put the method definitions in a separate cpp file and try to compile it the object file itself will not be generated with the class information. The compilation will not fail, it would generate the object file but it won't generate any code for the template class in the object file. This is the reason why the linker is unable to find the symbols in the object files and the build fails.
Now what is the alternative to hide important implementation details? As we all know the main objective behind separating interface from implementation is hiding implementation details in binary form. This is where you must separate the data structures and algorithms. Your template classes must represent only data structures not the algorithms. This enables you to hide more valuable implementation details in separate non-templatized class libraries, the classes inside which would work on the template classes or just use them to hold data. The template class would actually contain less code to assign, get and set data. Rest of the work would be done by the algorithm classes.
I hope this discussion would be helpful.
It is possible, as long as you know what instantiations you are going to need.
Add the following code at the end of stack.cpp and it'll work :
template class stack<int>;
All non-template methods of stack will be instantiated, and linking step will work fine.
You can do it in this way
// xyz.h
#ifndef _XYZ_
#define _XYZ_
template <typename XYZTYPE>
class XYZ {
//Class members declaration
};
#include "xyz.cpp"
#endif
//xyz.cpp
#ifdef _XYZ_
//Class definition goes here
#endif
This has been discussed in Daniweb
Also in FAQ but using C++ export keyword.
No, it's not possible. Not without the export keyword, which for all intents and purposes doesn't really exist.
The best you can do is put your function implementations in a ".tcc" or ".tpp" file, and #include the .tcc file at the end of your .hpp file. However this is merely cosmetic; it's still the same as implementing everything in header files. This is simply the price you pay for using templates.
Only if you #include "stack.cpp at the end of stack.hpp. I'd only recommend this approach if the implementation is relatively large, and if you rename the .cpp file to another extension, as to differentiate it from regular code.
I believe there are two main reasons for trying to seperate templated code into a header and a cpp:
One is for mere elegance. We all like to write code that is wasy to read, manage and is reusable later.
Other is reduction of compilation times.
I am currently (as always) coding simulation software in conjuction with OpenCL and we like to keep code so it can be run using float (cl_float) or double (cl_double) types as needed depending on HW capability. Right now this is done using a #define REAL at the beginning of the code, but this is not very elegant. Changing desired precision requires recompiling the application. Since there are no real run-time types, we have to live with this for the time being. Luckily OpenCL kernels are compiled runtime, and a simple sizeof(REAL) allows us to alter the kernel code runtime accordingly.
The much bigger problem is that even though the application is modular, when developing auxiliary classes (such as those that pre-calculate simulation constants) also have to be templated. These classes all appear at least once on the top of the class dependency tree, as the final template class Simulation will have an instance of one of these factory classes, meaning that practically every time I make a minor change to the factory class, the entire software has to be rebuilt. This is very annoying, but I cannot seem to find a better solution.
Sometimes it is possible to have most of implementation hidden in cpp file, if you can extract common functionality foo all template parameters into non-template class (possibly type-unsafe). Then header will contain redirection calls to that class. Similar approach is used, when fighting with "template bloat" problem.
If you know what types your stack will be used with, you can instantiate them expicitly in the cpp file, and keep all relevant code there.
It is also possible to export these across DLLs (!) but it's pretty tricky to get the syntax right (MS-specific combinations of __declspec(dllexport) and the export keyword).
We've used that in a math/geom lib that templated double/float, but had quite a lot of code. (I googled around for it at the time, don't have that code today though.)
The problem is that a template doesn't generate an actual class, it's just a template telling the compiler how to generate a class. You need to generate a concrete class.
The easy and natural way is to put the methods in the header file. But there is another way.
In your .cpp file, if you have a reference to every template instantiation and method you require, the compiler will generate them there for use throughout your project.
new stack.cpp:
#include <iostream>
#include "stack.hpp"
template <typename Type> stack<Type>::stack() {
std::cerr << "Hello, stack " << this << "!" << std::endl;
}
template <typename Type> stack<Type>::~stack() {
std::cerr << "Goodbye, stack " << this << "." << std::endl;
}
static void DummyFunc() {
static stack<int> stack_int; // generates the constructor and destructor code
// ... any other method invocations need to go here to produce the method code
}
The place where you might want to do this is when you create a library and header combination, and hide the implementation to the user. Therefore, the suggested approach is to use explicit instantiation, because you know what your software is expected to deliver, and you can hide the implementations.
Some useful information is here:
https://learn.microsoft.com/en-us/cpp/cpp/explicit-instantiation?view=vs-2019
For your same example:
Stack.hpp
template <class T>
class Stack {
public:
Stack();
~Stack();
void Push(T val);
T Pop();
private:
T val;
};
template class Stack<int>;
stack.cpp
#include <iostream>
#include "Stack.hpp"
using namespace std;
template<class T>
void Stack<T>::Push(T val) {
cout << "Pushing Value " << endl;
this->val = val;
}
template<class T>
T Stack<T>::Pop() {
cout << "Popping Value " << endl;
return this->val;
}
template <class T> Stack<T>::Stack() {
cout << "Construct Stack " << this << endl;
}
template <class T> Stack<T>::~Stack() {
cout << "Destruct Stack " << this << endl;
}
main.cpp
#include <iostream>
using namespace std;
#include "Stack.hpp"
int main() {
Stack<int> s;
s.Push(10);
cout << s.Pop() << endl;
return 0;
}
Output:
> Construct Stack 000000AAC012F8B4
> Pushing Value
> Popping Value
> 10
> Destruct Stack 000000AAC012F8B4
I however don't entirely like this approach, because this allows the application to shoot itself in the foot, by passing incorrect datatypes to the templated class. For instance, in the main function, you can pass other types that can be implicitly converted to int like s.Push(1.2); and that is just bad in my opinion.
You need to have everything in the hpp file. The problem is that the classes aren't actually created until the compiler sees that they're needed by some OTHER cpp file - so it has to have all the code available to compile the templated class at that time.
One thing that I tend to do is to try to split my templates into a generic non-templated part (which can be split between cpp/hpp) and the type-specific template part which inherits the non-templated class.
Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.
Another possibility is to do something like:
#ifndef _STACK_HPP
#define _STACK_HPP
template <typename Type>
class stack {
public:
stack();
~stack();
};
#include "stack.cpp" // Note the include. The inclusion
// of stack.h in stack.cpp must be
// removed to avoid a circular include.
#endif
I dislike this suggestion as a matter of style, but it may suit you.
The 'export' keyword is the way to separate out template implementation from template declaration. This was introduced in C++ standard without an existing implementation. In due course only a couple of compilers actually implemented it. Read in depth information at Inform IT article on export
1) Remember the main reason to separate .h and .cpp files is to hide the class implementation as a separately-compiled Obj code that can be linked to the user’s code that included a .h of the class.
2) Non-template classes have all variables concretely and specifically defined in .h and .cpp files. So the compiler will have the need information about all data types used in the class before compiling/translating  generating the object/machine code
Template classes have no information about the specific data type before the user of the class instantiate an object passing the required data type:
TClass<int> myObj;
3) Only after this instantiation, the complier generate the specific version of the template class to match the passed data type(s).
4) Therefore, .cpp Can NOT be compiled separately without knowing the users specific data type. So it has to stay as source code within “.h” until the user specify the required data type then, it can be generated to a specific data type then compiled
I am working with Visual studio 2010, if you would like to split your files to .h and .cpp, include your cpp header at the end of the .h file

"Undefined symbols" linker error with simple template class

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.