Using template instead of switch

前端 未结 5 1186
眼角桃花
眼角桃花 2020-12-13 22:42

I want to perform a set of tests in my code that are similar but change only depending on a parameter.

I could write this using a switch statement:

b         


        
5条回答
  •  轮回少年
    2020-12-13 22:44

    Building off Andrew's answer...

    Note that the EnumSensorFamily family must be known at compile time. If it is not known until run time, then you'll have to write a switch to choose the template, putting you back where you started.

    Another way to do this is with the Traits pattern:

    template 
    struct SensorTraits;
    
    template <>
    struct SensorTraits
    {
        const EnumSensorFamily kFamilyID = ExpectedFam1;
    };
    
    template <>
    struct SensorTraits
    {
        const EnumSensorFamily kFamilyID = ExpectedFam2;
    };
    
    template <>
    struct SensorTraits
    {
        const EnumSensorFamily kFamilyID = ExpectedFam3;
    };
    
    template 
    bool doTest(const StructSensorProposal& proposed)
    {
      return (SensorTraits::kFamilyID == proposed.Fam1SensorId);
    }
    

    If you try to use doTest with a sensor family that lacks a traits specialization, you get a compile error. Also note that you never instantiate a traits object, you just use its definitions.

    This lets you reuse constants, typedefs, whatever in several functions. Additionally, adding a new family does not involve combing through all the code looking for every switch statement that cares. All you have to do is create a new SensorTraits specialization.

    EDIT: You can make the field dependent on the sensor family with a pointer to member:

    template <>
    struct SensorTraits
    {
        const EnumSensorFamily kFamilyID = ExpectedFam1;
        int StructSensorProposal::*proposalField = &StructSensorProposal::fam1field;
    };
    
    // ...
    
    template 
    int getProposedField(const StructSensorProposal& proposed)
    {
        return proposed.*SensorTraits::proposalField;
    }
    

    You can also put in, say, a typedef for the sensor's data type:

    template <>
    struct SensorTraits
    {
        const EnumSensorFamily kFamilyID = ExpectedFam1;
        typedef uint16_t data_type;
        data_type StructSensorProposal::*proposalField = &StructSensorProposal::fam1field;
    };
    
    // ...
    
    template 
    SensorTraits::data_type getProposedField(const StructSensorProposal& proposed)
    {
        return proposed.*SensorTraits::proposalField;
    }
    

    I haven't tested these; you might need a const or static in there.

提交回复
热议问题