Шаблонная конструкция нешаблонного класса

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

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> и т. д. Как я могу добиться аналогичного построения времени компиляции при сохранении одного типа класса.


person Michael George    schedule 13.09.2011    source источник
comment
Это похоже на stackoverflow.com/q/874298/918124.   -  person DrYap    schedule 13.09.2011
comment
Ваш пример не должен компилироваться.   -  person Cheers and hth. - Alf    schedule 13.09.2011
comment
Нет такой вещи, как Sensor.   -  person John Dibling    schedule 13.09.2011


Ответы (3)


На первый взгляд это кажется достаточно простым, просто используйте шаблонный конструктор в классе 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 );
}

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

Так что на самом деле это должен быть аргумент необработанных данных, который должен быть введен.

Более строгая типизация необработанных данных также поможет вам избежать ошибок, например. Необработанные данные радара обрабатываются как необработанные данные 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 и в класс, несущий необработанные данные радара.

Ура и чт.,

person Cheers and hth. - Alf    schedule 13.09.2011

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

person Mark B    schedule 13.09.2011

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

template<SensorTypes>
class DerivedSensor : public Sensor
{
public:
    DerivedSensor(unsigned char* rawdata){//Format of rawdata depends on SensorTypes};
};
person Mark Ransom    schedule 13.09.2011
comment
Я действительно ищу шаблонное решение, которое соответствует устаревшему коду (т.е. принимает типы Sensor, а не Sensor<GPS> или DerivedSensor) и позволяет избежать виртуальных методов, необходимости повышать или распространять производные классы для более длинных перечислений. - person Michael George; 13.09.2011
comment
@ Майкл Джордж, может быть, я не понимаю вопроса - вы хотите создать объекты Sensor, но хотите, чтобы у них были разные конструкторы на основе перечисления, верно? Есть ли что-то кроме конструктора, зависящее от перечисления? - person Mark Ransom; 13.09.2011