I have a header class that looks like this:
#ifndef A_H__
#define A_H__
using namespace pcl::tracking;
namespace ball_tracking_cloud
{
template <typename PointType>
class OpenNISegmentTracking
{
public:
//...
protected:
void update(const sensor_msgs::PointCloud2ConstPtr &input_cloud);
}; // end of class
} // end namespace
#endif
And now I have a .cpp file that looks like this:
#include <ball_tracking_cloud/particle_detector.h>
bool init = true;
namespace ball_tracking_cloud
{
void OpenNISegmentTracking<pcl::PointXYZRGBA>::update(const sensor_msgs::PointCloud2ConstPtr &input_cloud)
{
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBA>);
pcl::fromROSMsg(*input_cloud, *cloud);
if(init)
{
v.run ();
init=false;
}
v.cloud_cb(cloud);
}
} // end of namespace
If I compile my code I get this error:
: error: specializing member ‘ball_tracking_cloud::OpenNISegmentTracking<pcl::PointXYZRGBA>::update’ requires ‘template<>’ syntax
void OpenNISegmentTracking<pcl::PointXYZRGBA>::update(const sensor_msgs::PointCloud2ConstPtr &input_cloud)
^
/hri/localdisk/markus/ros-alex/src/ball_tracking/ball_tracking_cloud/src/particle_detector.cpp:38:1: error: expected ‘}’ at end of input
} // end of namespace
^
I am not sure why I get this error..... I guess it has something to do with the fact that I use a template class ..... but I am not sure about this....
Any help would be great!
Your OpenNISegmentTracking is what in c++ terms is called a full template specialization.
In other words, it's a version of your template that will be invoked, only when the template parameter is a pcl::PointXYZRGBA.
The proper syntax for such a definition is
template <>
void OpenNISegmentTracking<pcl::PointXYZRGBA>::update(const sensor_msgs::PointCloud2ConstPtr &input_cloud)
{
...
}
You need this syntax for the function name:
template<>
void OpenNISegmentTracking<pcl::PointXYZRGBA>::update(const sensor_msgs::PointCloud2ConstPtr &input_cloud)
{
// ...
}
Related
all!
I want write a template structure, which will give me concrete name of a class based on enum. In details:
in .h file
#include "Mish.h"
#include "ReLU.h"
namespace a
{
namespace b
{
enum class ActivationEnum : size_t
{
Mish,
ReLU
};
template <ActivationEnum act>
struct Activation
{
};
template <>
struct Activation<ActivationEnum::Mish>
{
using aType = Mish;
};
template <>
struct Activation<ActivationEnum::ReLU>
{
using aType = ReLU;
};
} // raul namespace
}
Then I want to use it in code as:
void someF(..., ActivationEnum act)
{
...
OtherClass<Activation<act>::aType> bla;
...
}
I've faced with two problems:
Mish and ReLU are implemented in Mish.cpp and ReLU.cpp files in namespace a, includes are here, but I got errors syntax error: identifier 'ReLU' and syntax error: identifier 'Mish'. If I add forward declaration here such as namespace a { class Mish; class ReLU; ... } then everything is ok here.
No matter in function someF I receive invalid template argument for 'a::b::Activation', expected compile-time constant expression
What are the problems? How can I return different typenames based on enum? Thank you.
With the below code:
materia.h:
#ifndef MATERIA_H
#define MATERIA_H
class material
{
public:
template <class type>
static material* MakeMaterial(typename type::configtype, long);
template <class type>
void CreateNaturalForm(typename type::configtype, long);
…
};
template <class type>
material* material::MakeMaterial(typename type::configtype Config, long Volume)
{
return type::Spawn(Config, Volume);
}
#endif
materias.h:
#ifndef MATERIAS_H
#define MATERIAS_H
#include "materia.h"
#include "confdef.h"
class solid : public material {
public:
typedef solidmaterial configtype;
…
};
template material* material::MakeMaterial<solid>(solidmaterial, long);
template <class type>
void material::CreateNaturalForm(typename type::configtype Config, long Volume)
{
…
MakeMaterial(Config, Volume); // Error here
…
}
template void material::CreateNaturalForm<solid>(solidmaterial, long);
#endif
confdef.h:
#ifndef CONFDEF_H
#define CONFDEF_H
enum solidmaterial {
WOOD,
…
};
#endif
main.cpp
#include "materia.h"
#include "materias.h"
#include "confdef.h"
int main()
{
material::MakeMaterial(WOOD, 500); // Same error here
}
(Here's an online version of the above code that reproduces the error.)
I get the following compilation error message on the commented line:
No matching function for call to 'MakeMaterial'
What am I doing wrong? Shouldn't the explicit instantiation allow the compiler to see the correct function?
The code compiles if I write MakeMaterial<solid> explicitly, but the whole point here is to deduce type from the Config argument. How can I achieve this?
In the call
MakeMaterial(Config, Volume); // Error here
the compiler is asked to find a match where type::configtype in the function template, is the type of Config.
But nothing tells the compiler what to match type to: this is not an explicit instantiation.
In general there could be hundreds of types that type could be matched to, where type::configtype would be the type of Config. C++ does not support the special case where there is only one such possible type.
How to fix that depends on what you meant to accomplish.
I've specified a header file like this:
04-Templates_foo.h:
template <typename T>
class foo {
T x, y;
T getX(void);
void setX(T x);
};
And an implementation like this:
04-Templates_foo.cc:
#include "04-Templates_foo.h"
template <typename T>
T foo::getX(void) {
return this->x;
}
void foo::setX(T x) {
this->x = x;
}
My main routine:
04-Templates.cc
#include <iostream>
#include "04-Templates_foo.cc"
int main (void) {
// Do nothing because it doesn't even compile...
}
Compiling this code returns this error:
In file included from 04-Templates.cc:2:
./04-Templates_foo.cc:4:3: error: expected a class or namespace
T foo::getX(void) {
^
1 error generated.
I can't imagine what the problem is. Why can't I specify the function foo::getX? It's a class name, although the compiler said it is expecting a class and didn't find one :-/
If it may be important. I'm compiling this on a MacBook Pro Retina Mid 2012 with Mavericks.
I used this compile-command:
g++ -o 04-Templates 04-Templates.cc
Suggestions for a better title are welcome ;)
In the definition of foo::getX (and setX as well), what kind of foo?
Because it's a template class, you have to specify that, like
template<typename T>
T foo<T>::getX(void) { ... }
You also have to tell the compiler that member functions are templates for each function in a templated class. So you have to do it for setX as well:
template<typename T>
void foo<T>::setX(T x) { ... }
I've seen some responses to the too few template-parameter-lists problem in classes but I'm getting a similar error in a header file where the declarations seem to be at the name space level. I'm not at all a C++ guy, but I want to figure out what I need to correct in this file to prevent the following error regarding the two lines after the typedef:
too few template-parameter-lists
Here's a file experpt
#ifndef SH_AUDATA_H
#define SH_AUDATA_H
#include "BinaryIO.h"
#include "AudioData.h"
// AuMuLawAudioData
typedef AudioDataImpl<AuMuLaw,BYTE> AuMuLawAudioData ;
inline BYTE AuMuLawAudioData::readValue (BinaryIO* io) const { return (io->read8()) ; }
inline void AuMuLawAudioData::writeValue (BinaryIO* io, BYTE v) const { io->write8(v) ; }
#endif // ndef SH_AUDATA_H
Thanks!
You either need to
indicate your defining a template member using template<> (http://ideone.com/ZWYuCd)
or you should just use the full qualified class name (http://ideone.com/zsmHjG)
Contrast both:
template <typename T> struct X
{
T v;
void foo();
};
typedef X<int> SomeTypedef;
#if 0
template<> void SomeTypedef::foo() {
//
}
#else
template <typename T> void X<T>::foo() {
//
}
#endif
int main()
{
SomeTypedef a;
a.foo();
}
Both the approaches to define foo will work (change #if 0 to #if 1 to "select" the other approach)
I have a C++/Win32/MFC project in Visual Studio 2008, and I'm getting a strange error message when I compile it.
I've created a small project to demonstrate the problem, and the main code is
#ifndef _MyObject_h
#define _MyObject_h
class MyObject
{
public:
MyObject()
{
}
};
#endif // _MyObject_h
// --- END MyObject.h
// --- BEGIN ObjectData.h
#ifndef _ObjectData_h
#define _ObjectData_h
template <typename DataPolicy>
class ObjectData
{
public:
DataPolicy *data;
ObjectData() :
data(NULL)
{
}
ObjectData(const ObjectData<DataPolicy> ©) :
data(copy.data)
{
}
ObjectData<DataPolicy> & operator=(const ObjectData<DataPolicy> ©)
{
this->data = copy.data;
return *this;
}
};
#endif // _ObjectData_h
// --- END ObjectData.h
// --- BEGIN Tool.h
#ifndef _Tool_h
#define _Tool_h
#include "ObjectData.h"
template <typename ObjectPolicy>
class Tool
{
private:
ObjectData<typename ObjectPolicy> _object;
public:
Tool(ObjectData<typename ObjectPolicy> obj);
};
#endif // _Tool_h
// --- END Tool.h
// --- BEGIN Tool.cpp
#include "stdafx.h"
#include "Tool.h"
template <typename ObjectPolicy>
Tool<ObjectPolicy>::Tool(ObjectData<typename ObjectPolicy> obj) :
_object(obj)
{
}
// --- END Tool.cpp
// --- BEGIN Engine.h
#ifndef _Engine_h
#define _Engine_h
#include "Tool.h"
#include "MyObject.h"
class Engine
{
private:
MyObject *_obj;
public:
Engine();
~Engine();
void DoSomething();
};
#endif // _Engine_h
// --- END Engine.h
// --- BEGIN Engine.cpp
#include "stdafx.h"
#include "Engine.h"
Engine::Engine()
{
this->_obj = new MyObject();
}
Engine::~Engine()
{
delete this->_obj;
}
void Engine::DoSomething()
{
ObjectData<MyObject> objData;
objData.data = this->_obj;
// NEXT LINE IS WHERE THE ERROR OCCURS
Tool< ObjectData<MyObject> > *tool = new Tool< ObjectData<MyObject> >(objData);
}
// --- END Engine.cpp
Errors:
Engine.cpp
c:\projects\myproject\myproject\engine.cpp(18) : error C2664: 'Tool::Tool(ObjectData)' : cannot convert parameter 1 from 'ObjectData' to 'ObjectData'
with
[
ObjectPolicy=ObjectData,
DataPolicy=ObjectData
]
and
[
DataPolicy=MyObject
]
and
[
DataPolicy=ObjectData
]
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>Build log was saved at "file://c:\Projects\MyProject\MyProject\Debug\BuildLog.htm"
MyProject - 1 error(s), 0 warning(s)
Thanks for any help.
There are a few problems with your code. First of all, you are using the typename keyword in a wrong way. typename can be used only when qualified type names are used (and is required when the type names are dependent), which is not your case:
template <typename ObjectPolicy>
class Tool
{
private:
ObjectData<typename ObjectPolicy> _object; // "typename" is not needed!
public:
Tool(ObjectData<typename ObjectPolicy> obj); // "typename" is not needed!
};
The problem you complain about, however, is in your instantiation of the Tool class template:
Tool< ObjectData<MyObject> > *tool = new Tool< ObjectData<MyObject> >(objData);
Your Tool<> template contains a member variable of type ObjectData<ObjectPolicy>, where ObjectPolicy is the class template parameter. However, in the line above you instantiate Tool with ObjectData<MyObject> as a parameter. This means your member variable will have type ObjectData<ObjectData<MyObject>>, and this will also be the type of the constructor's parameter.
Because of this, you are trying to invoke a constructor which accepts an ObjectData<ObjectData<MyObject>> with an argument of a mismatching type ObjectData<MyObject>. Hence, the error you get.
You should change your instantiation into:
Tool< MyObject > *tool = new Tool< MyObject >(objData);
Another problem is that you have the definition of Tool's member functions in a separate .cpp files. You should not do that: the linker won't be able to see it when processing a separate translation unit.
To solve this problem, put the definitions of your class template's member functions into the same header where the class template is defined (Tool.h in your case).
Tool< ObjectData<MyObject> > *tool = new Tool< ObjectData<MyObject> >(objData);
template <typename ObjectPolicy>
Tool<ObjectPolicy>::Tool(ObjectData<typename ObjectPolicy> obj) :
_object(obj)
{
}
It seems to me you might not really understand how templates work.
Check out the following C++ Templates
What you currently have is invalid C++ syntax. Take a look and give it another shot.