Я хочу создать процессор во ворин (как этот .CPP | .час) портируем это OTB-приложение:
http://hg.orfeo-toolbox.org/OTB/file/ca4366bb972e/Applications/Segmentation/otbSegmentation.cxx
Я закодировал почти все параметры в свойствах и т. Д., Но …
Если вы посмотрите на как 376, вы увидите шаблон класса FloatVectorImageType :: SizeType, тип определения типа.
Я не знаком с шаблонами c ++, поэтому мой первый вопрос был, где я должен поместить реализацию этого шаблона, в файл .cpp или .h процессора? Кратко рассмотрим учебники по c ++ и другие примеры процессоров, такие как один выше, Я понял, что должен объявить шаблон в заголовке и определить его в .cpp.
Проблема в том, что компилятор не позволяет мне определять шаблонный класс типа typedef внутри .cpp. Тип определения не распознан ..
Итак, кто-то может указать мне правильное направление здесь?
segmentationprocessor.h
#ifndef OTBSEGMENTATIONAPPLICATION_H
#define OTBSEGMENTATIONAPPLICATION_H
#include "otbVectorImage.h"#include "modules/otb/ports/otbimageport.h"#include "modules/otb/ports/otbvectorimageport.h"#include "voreen/core/properties/boolproperty.h"
//..more includes here
namespace voreen {
class OTBSegmentationApplication : public OTBImageFilterProcessor
{
public:
OTBSegmentationApplication();
virtual ~OTBSegmentationApplication();
virtual Processor* create() const;
virtual std::string getCategory() const { return "Applications"; }
virtual std::string getClassName() const { return "Segmentation Application"; }
virtual CodeState getCodeState() const { return CODE_STATE_EXPERIMENTAL;}//STABLE, TESTING, EXPERIMENTAL
virtual std::string getProcessorInfo() const;
/** Images typedefs */
typedef otb::VectorImage<double, 2> VectorImageType;
typedef ImageType LabelImageType;
typedef ImageType MaskImageType;
typedef VectorImageType::SizeType size;
// Segmentation filters typedefs
// Edison mean-shift
typedef otb::MeanShiftVectorImageFilter<VectorImageType,VectorImageType,LabelImageType> EdisonSegmentationFilterType;
EdisonSegmentationFilterType::Pointer edisonFilter;
// Home made mean-shift
typedef otb::MeanShiftSegmentationFilter<VectorImageType, LabelImageType, VectorImageType> MeanShiftSegmentationFilterType;
MeanShiftSegmentationFilterType::Pointer meanshiftFilter;
// Simple connected components
typedef otb::Functor::ConnectedComponentMuParserFunctor<VectorImageType::PixelType> FunctorType;
typedef itk::ConnectedComponentFunctorImageFilter <VectorImageType, LabelImageType, FunctorType, MaskImageType> ConnectedComponentSegmentationFilterType;
ConnectedComponentSegmentationFilterType::Pointer ccFilter;
typedef itk::ScalarConnectedComponentImageFilter<LabelImageType, LabelImageType> LabeledConnectedComponentSegmentationFilterType;
LabeledConnectedComponentSegmentationFilterType::Pointer labeledCCFilter;
//..more typedefs here
protected:
virtual void setDescriptions() {
setDescription("Performs segmentation of an image, and output either a raster or a vector file. In vector mode, large input datasets are supported.");
}
void process();
virtual void initialize() throw (tgt::Exception);
virtual void deinitialize() throw (tgt::Exception);
/** TEMPLATE DECLARATION (?) */
template<class TInputImage, class TSegmentationFilter>
VectorImageType::SizeType GenericApplySegmentation(otb::StreamingImageToOGRLayerSegmentationFilter
<TInputImage, TSegmentationFilter> * streamingVectorizedFilter, TInputImage * inputImage,
const otb::ogr::Layer& layer, const unsigned int outputNb);
virtual void updateFilterSelection();
virtual void updateModeSelection();
private:
OTBVectorImagePort inPort_;
StringOptionProperty filter_; ///< Select segmentation algorithm
OTBVectorImagePort vectorOutPort_;
OTBImagePort vectorMaskInPort_;
OTBImagePort outPort_;
//..more property definitions here
static const std::string loggerCat_; ///< Category used in logging
};
} // namespace
#endif // OTBSEGMENTATIONAPPLICATION_H
segmentationprocessor.cpp
#include "segmentationprocessor.h"#include "voreen/core/voreenapplication.h"
namespace voreen {
const std::string OTBSegmentationApplication::loggerCat_("voreen.OTBSegmentationApplication");
OTBSegmentationApplication::OTBSegmentationApplication()
:OTBImageFilterProcessor(),
inPort_(Port::INPORT, "IN Multiband Image", 0),
vectorOutPort_(Port::OUTPORT, "OUT Multiband Image", 0),
vectorMaskInPort_(Port::INPORT, "IN Mask Image", 0),
outPort_(Port::OUTPORT, "OUT OTB Image", 0),
filter_("selectFilter", "Segmentation algorithm"),
//.. more properties code here
{
addPort(inPort_);
addPort(vectorOutPort_);
addPort(vectorMaskInPort_);
addPort(outPort_);
addProperty(filter_);
//.. adding the rest of properties here
edisonFilter = EdisonSegmentationFilterType::New();
meanshiftFilter = MeanShiftSegmentationFilterType::New();
ccFilter = ConnectedComponentSegmentationFilterType::New();
//..instantiating more filters needed in implementation here
}
Processor* OTBSegmentationApplication::create() const {
return new OTBSegmentationApplication();
}
OTBSegmentationApplication::~OTBSegmentationApplication() {
}
void OTBSegmentationApplication::initialize() throw (tgt::Exception) {
Processor::initialize();
}
void OTBSegmentationApplication::deinitialize() throw (tgt::Exception) {
Processor::deinitialize();
}
std::string OTBSegmentationApplication::getProcessorInfo() const {
return "Segmentation Application";
}
void OTBSegmentationApplication::updateFilterSelection() {
//code for visual updates on properties here
}
void OTBSegmentationApplication::updateModeSelection() {
//code for visual updates on properties here
}
//TEMPLATE IMPLEMENTATION HERE (?)
template<class TInputImage, class TSegmentationFilter>
OTBSegmentationApplication::VectorImageType::SizeType OTBSegmentationApplication::GenericApplySegmentation(otb::StreamingImageToOGRLayerSegmentationFilter<TInputImage,
TSegmentationFilter> * streamingVectorizedFilter, TInputImage * inputImage, const otb::ogr::Layer& layer, const unsigned int outputNb)
{
typedef TSegmentationFilter SegmentationFilterType;
typedef typename SegmentationFilterType::Pointer SegmentationFilterPointerType;
typedef otb::StreamingImageToOGRLayerSegmentationFilter<TInputImage,SegmentationFilterType> StreamingVectorizedSegmentationOGRType;
//..the rest of template code here
}void OTBSegmentationApplication::process() {
try
{
//PROCESSOR IMPLEMENTATION GOES HERE
LINFO("Segmentation Application Connected");
}
catch (int e)
{
LERROR("Error in Segmentation Applicationn");
return;
}
}
} // namespace
ошибка: «VectorImageType» не называет тип (исправлено)
Я не знаком с шаблонами c ++, поэтому мой первый вопрос был, где я должен поместить реализацию этого шаблона, в файл .cpp или .h процессора?
Поместите это в заголовочный файл. Это самое простое и надежное решение. Как правило, вы хотите поместить определения функций (то есть их тело функции) в исходные файлы (.cpp), так как исходные файлы могут быть скомпилированы независимо. Но это не возможно для шаблонов(*).
(*) немного упрощено.
Шаблоны классов это просто чертежи для занятий, шаблоны функций чертежи для функций. То есть, шаблоны функций не являются функциями, другими словами, «функция шаблона» вводит в заблуждение, это не функция, а шаблон / план.
Процесс построения функции из шаблона функции (или класса из шаблона класса) называется конкретизации. Результатом является конкретизированная функция или, в более общем смысле, шаблон функции специализация.
Шаблонные специализации нет шаблонов. Специализация шаблона функции — это обычная функция со странным именем; специализация шаблона класса — это просто класс со странным именем.
Шаблон будет создан только для некоторых конкретных наборов аргументов шаблона:
Второй способ, безусловно, более распространенный. Пример:
template<class T>
struct my_type
{
T mem;
};
// using the specialization -> implicit instantiation
my_type<int> o;
my_type<double> p;
Это будет создавать шаблон класса my_type
один раз для аргумента шаблона int
и один раз для аргумента шаблона double
, Это создает два независимый а также несвязанный типы с похожими именами: my_type<int>
а также my_type<double>
И аналогично для функций; кроме того, что для функций, вы, как правило, не предоставляйте явно аргументы шаблона. Вместо этого вы позволяете компилятору выводить аргументы шаблона из типов аргументов функции. Пример:
template<class T>
void foo(T param)
{
std::cout << param;
}
foo<int>(42); // explicitly specifying the template arguments -- DON'T DO THAT
foo(21); // template argument *deduction*
Второй звонок будет автоматически выводить аргумент шаблона должен быть int
, Опять же, мы создали (неявно созданы) две функции с похожими именами: foo<int>(int)
(имя foo<int>
и он имеет единственный параметр функции типа int
) а также foo<double>(double)
Почему плохо помещать определения шаблонов в исходный файл: см. Почему шаблоны могут быть реализованы только в заголовочном файле?
Краткая версия: поскольку шаблоны являются чертежами, для их использования компилятор должен создавать их экземпляры. Но это может только создать экземпляр того, что это знает.
Если вы объявите шаблон функции foo
в заголовочном файле templ.h
определите это в templ.cpp
и использовать его в main.cpp
, затем:
В main.cpp
компилятор не знает об определении шаблона функции. Это может только создать экземпляр декларация из foo
, но не определение.
В templ.cpp
Компилятор знает об определении и может его создать. Тем не менее, он не знает об использовании за пределами templ.cpp
— следовательно, он не может создать экземпляр для всех наборов аргументов, используемых снаружи.
В примере в OP это работает, но, похоже, это упущение:
[Templ.h]template<class T>
void foo(T);
void ordinary_function();
[Templ.cpp]
#include "templ.h"
template<class T>
void foo(T p)
{
std::cout << p;
}
void ordinary_function()
{
foo(42); // implicit instantiation of foo<int>
foo(2.5); // implicit instantiation of foo<double>
}
[Main.cpp]
#include "templ.h"int main()
{
foo(23); // works fine, uses the foo<int> defined in templ.cpp
foo('a'); // linker error: foo<char> not defined
return 0;
}
Поскольку определение из foo<char>
не был создан в templ.cpp
и не может быть создан в main.cpp
, это приводит к ошибке компоновщика.
Вот почему вы не должны полагаться на это поведение. Ты можешь использовать явная реализация если вы по какой-то причине не хотите определить шаблон функции в заголовочном файле. По крайней мере, явная реализация является явной и должна быть задокументирована, чтобы не было никаких неожиданностей.
Проблема, на которую на самом деле жалуется компилятор, не имеет ничего общего с шаблонами;) Это просто проблема поиска имени. Упрощенный пример:
#include <iostream>
struct Foo
{
typedef int Bar;
void do_something();
};
Bar Foo::do_something()
{
std::cout << "something\n";
}
Когда компилятор видит строку Bar Foo::do_something()
это видит Bar
и не может найти то, к чему относится это имя. Отсюда и ошибка. С другой стороны:
#include <iostream>
struct Foo
{
typedef int Bar;
void do_something();
};
Foo::Bar Foo::do_something()
{
std::cout << "something\n";
}
Теперь вы сказали компилятору, где искать имя Bar
а именно внутри Foo
,
Вот краткий пример шаблонов, которые я написал, чтобы помочь вам:
в заголовке:
typedef TemplatedClassName< ParameterValue0, ParameterValue1 > TemplateAlias;
в исходном файле:
// явная реализация шаблона
template class TemplatedClassName< ParameterValue0, ParameterValue1 >;