非模板类的模板化构造

发布于 2024-12-04 12:23:10 字数 545 浏览 1 评论 0原文

我有一个具有公共成员的类,但需要基于枚举以有限数量的方式构造。每种类型在编译时都是已知的,因此我认为模板在这里有意义。我知道我可以通过构造函数专门化来解决这个问题,例如:

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 等。我怎样才能实现类似的目标编译时构造,同时保持单个类类型。

I have a class that has common members but needs to be constructed in a finite number of ways based on an enumeration. Each type is known at compile time, so I am thinking templates make sense here. I know I can solve this with constructor specialization, e.g.:

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];}

The problem is I have legacy code which must accept Sensor classes not Sensor<GPS> etc. How can I achieve similar compile time construction while maintaining a single class type.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微暖i 2024-12-11 12:23:10

乍一看这似乎很简单,只需在 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 参数。

使原始数据的类型更加严格还可以帮助您避免错误,例如雷达原始数据被视为 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构造函数和类中移出,并转移到携带雷达原始数据的类中。

干杯&呵呵,,

This seems simple enough at first, just use a templated constructor in the Sensor class.

#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 );
}

But at this point it's easy to see that the "type-argument" is really describing the rawdata, and nothing else.

So really, it should be the rawdata argument that should be typed.

Making the rawdata more strictly typed also helps you avoid foul-ups were e.g. radar rawdata is treated as GPS rawdata.

#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 );
}

Design-wise, this is partitioning into rawdata providers and rawdata interpreters (the Sensor class is evidently a rawdata interpreter).

That design is implied by the question, but if may be that it could be beneficial to move the interpretation knowledge closer to the data sources.

I.e., to move the interpretation of e.g. radar data out of the Sensor constructor and class, and into the class carrying radar rawdata.

Cheers & hth.,

诺曦 2024-12-11 12:23:10

根据您的特定需求,您也许能够创建非模板基类并派生特定于模板的版本,使用虚拟方法来选择正确的行为。

Depending on your specific needs, you may be able to create a non-template base class and derive the template-specific version, using virtual methods to select the right behavior.

他不在意 2024-12-11 12:23:10

这看起来很简单,只需让您的模板类从现有的 Sensor 类派生即可。

template<SensorTypes>
class DerivedSensor : public Sensor
{
public:
    DerivedSensor(unsigned char* rawdata){//Format of rawdata depends on SensorTypes};
};

This seems simple enough, just have your template class derive from the existing Sensor class.

template<SensorTypes>
class DerivedSensor : public Sensor
{
public:
    DerivedSensor(unsigned char* rawdata){//Format of rawdata depends on SensorTypes};
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文