Шаблонная конструкция не шаблонного класса - PullRequest
0 голосов
/ 13 сентября 2011

У меня есть класс, который имеет общие члены, но должен быть построен конечным числом способов на основе перечисления.Каждый тип известен во время компиляции, поэтому я думаю, что шаблоны имеют здесь смысл.Я знаю, что могу решить эту проблему с помощью специализации конструктора, например:

enum SensorTypes{GPS,Radar,ShaftEncoder};

template<SensorTypes>
class Sensor
{
public:
    Sensor(unsigned char* rawdata){//Format of rawdata depends on SensorTypes};
private:
    double speed;
    double time;
}
template<> Sensor<GPS>::Sensor(unsigned char* rawdata){speed = (double)rawdata[0];}

Проблема в том, что у меня есть устаревший код, который должен принимать Sensor классов, а не Sensor<GPS> и т. Д. Как я могу добиться подобного построения во время компиляции, покаподдержание одного типа класса.

Ответы [ 3 ]

2 голосов
/ 13 сентября 2011

Поначалу это кажется достаточно простым, просто используйте шаблонный конструктор в классе Sensor.

#include <stdio.h>

namespace sensorKind {
    struct GPS {};
    struct Radar {};
    struct ShaftEncoder {};
}

class Sensor
{
public:
    template< class Kind >
    Sensor( Kind, unsigned char const* rawdata );
private:
    double speed_;
    double time_;
};

template<>
Sensor::Sensor(
    sensorKind::GPS,
    unsigned char const* rawData
    )
{
    printf( "Sensor<GPS> object created.\n" );
}

template<>
Sensor::Sensor(
    sensorKind::Radar,
    unsigned char const* rawData
    )
{
    printf( "Sensor<Radar> object created.\n" );
}

int main()
{
    Sensor  aGPSSensor( sensorKind::GPS(), 0 );
    Sensor  aRadarSensor( sensorKind::Radar(), 0 );
}

Но на этом этапе легко увидеть, что «аргумент типа» действительно описываетrawdata и ничего больше.

На самом деле, должен быть введен аргумент rawdata.

Более строгая типизация rawdata также помогает избежать путаницы, например, когда радар rawdataобрабатывается как необработанные данные GPS.

#include <stdio.h>

namespace sensor {
    struct Kind {
        enum  Enum{ gps, radar, shaftEncoder };
    };

    template< Kind::Enum aKind >
    class DataFrom 
    {
    public:
        static Kind::Enum const kind = aKind;

        unsigned char const* ptr() const { return 0; }
        DataFrom() {}
    };
}  // namespace sensor

class Sensor
{
public:
    typedef sensor::Kind    Kind;

    template< class DataKind >
    explicit Sensor(  DataKind const& rawData );
private:
    double speed_;
    double time_;
};

template<>
Sensor::Sensor( sensor::DataFrom< Kind::gps > const& rawData )
{
    printf( "%s\n", "Sensor<GPS> object created." );
}

template<>
Sensor::Sensor( sensor::DataFrom< Kind::radar > const& rawData )
{
    printf( "%s\n", "Sensor<Radar> object created." );
}

int main()
{
    sensor::DataFrom< sensor::Kind::gps >   gpsData;
    sensor::DataFrom< sensor::Kind::radar > radarData;

    Sensor  aGPSSensor( gpsData );
    Sensor  aRadarSensor( radarData );
}

В плане проектирования это разделение на поставщиков необработанных данных и интерпретаторов необработанных данных (класс Sensor, очевидно, является интерпретатором необработанных данных).

Это подразумеваемое проектированиевопрос, но если может , то было бы полезно приблизить знание интерпретации к источникам данных.

Т.е., переместить интерпретацию, например, радиолокационных данных из Sensor конструктор и класс, а в класс несут радарные необработанные данные.

Приветствия & hth.,

0 голосов
/ 13 сентября 2011

Это кажется достаточно простым, просто получите ваш шаблонный класс из существующего Sensor класса.

template<SensorTypes>
class DerivedSensor : public Sensor
{
public:
    DerivedSensor(unsigned char* rawdata){//Format of rawdata depends on SensorTypes};
};
0 голосов
/ 13 сентября 2011

В зависимости от ваших конкретных потребностей вы можете создать базовый класс, не относящийся к шаблону, и получить версию для конкретного шаблона, используя виртуальные методы для выбора правильного поведения.

...