constexpr construction of a POD struct with a char[] field

偶尔善良 提交于 2021-02-11 15:52:06

问题


How can I make the function below constexpr?

This is a function that I use to create a POD struct that is defined in a "C" header file that I cannot change.

I ended up with the following static function helper (which works) to make these structs, I believe it is not constexpr, as the strncpy call violates constexpr.

static auto makeWPTEntry(
    const char* name,
    double aLatDeg, double aLatMin, double aLonDeg,
    double aLonMin, char bSeven = false,
    double aCourse = 0, double aAzimuth = 0, double aDist = 0,
    int aETASecs = 0, int aMod = 0)->WPTEntry {
    auto result = WPTEntry{
        bSeven,
        {},
        (aLatDeg + aLatMin) / 60.0,
        (aLonDeg + aLonMin) / 60.0,
        aCourse, aAzimuth,
        aDist, aETASecs, aMod
    };
    strncpy(result.name, name, sizeof(result.name));
    return result;
}

I an struggling to make something along the following lines (which is constexpr) - however I really need the non constexpr function signature with a const char* name parameter, Unfortunately, I don't know how to inline convert this const char* into a fixed sized array char const (&name)[SIZ_WAYPOINT_NAME] to be compatible with the struct field's constructor.

constexpr auto makeWPTEntry(
    char const (&name)[SIZ_WAYPOINT_NAME],
    double aLatDeg, double aLatMin, double aLonDeg,
    double aLonMin, char bSeven = false,
    double aCourse = 0, double aAzimuth = 0,
    double aDist = 0,
    int aETASecs = 0, int aMod = 0)->WPTEntry {
    auto result = WPTEntry{
        bSeven,
        name,
        (aLatDeg + aLatMin) / 60.0,
        (aLonDeg + aLonMin) / 60.0,
        aCourse, aAzimuth,
        aDist, aETASecs, aMod
    };
    //strncpy(result.name, name, sizeof(result.name));
    return result;
}

The WPTEntry is a simple external C data structure.

#define SIZ_WAYPOINT_NAME 9

typedef struct {
    char    seven;
    char    name[SIZ_WAYPOINT_NAME];
    double  lat;        
    double  lon;        
    double  crs;        
    double  az2;        
    double  distance;   
    int     eta_secs;  
    int     mod;
} WPTEntry;

The way I create these structures is as follows:

const auto wpt = makeWPTEntry("", -24.499, 0, -81.501, 0);

I asked something similar question before, however I never received an answer.

I found the following from this site but I am not sure how I might be able to use it to adapt my parameter, perhaps its might be useful of not.

struct ArrayWrapper
{
   char const *address_;
   size_t      length_;

   template<int N>
   ArrayWrapper(char const (&array)[N])
   {
      address = &array[0];
      length_ = N;
   }
};

回答1:


A bit of twiddling around std::integer_sequence and I got it:

#include <utility>
#include <iostream>

extern "C" {
    #define SIZ_WAYPOINT_NAME 9

typedef struct {
    char    seven;
    char    name[SIZ_WAYPOINT_NAME];
    double  lat;        
    double  lon;        
    double  crs;        
    double  az2;        
    double  distance;   
    int     eta_secs;  
    int     mod;
} WPTEntry;

};

template<std::size_t N, std::size_t... I>
constexpr WPTEntry makeWPTEntry_in(
        char const (&name)[N],
        double aLatDeg, double aLatMin, double aLonDeg,
        double aLonMin, char bSeven,
        double aCourse, double aAzimuth,
        double aDist,
        int aETASecs, int aMod,
        std::index_sequence<I...>) {
    return WPTEntry{
        bSeven,
        { name[I]... },
        (aLatDeg + aLatMin) / 60.0,
        (aLonDeg + aLonMin) / 60.0,
        aCourse, aAzimuth,
        aDist, aETASecs, aMod
    };
}

template<std::size_t N, typename Indices = std::make_index_sequence<N>>
constexpr WPTEntry makeWPTEntry(
            char const (&name)[N],
            double aLatDeg, double aLatMin, double aLonDeg,
            double aLonMin, char bSeven = false,
            double aCourse = 0, double aAzimuth = 0,
            double aDist = 0,
            int aETASecs = 0, int aMod = 0) {
    return makeWPTEntry_in(name, 
        aLatDeg, aLatMin, aLonDeg,
        aLonMin, bSeven,
        aCourse, aAzimuth,
        aDist,
        aETASecs, aMod,
        Indices{});
}

int main() {
    const auto wpt = makeWPTEntry("", -24.499, 0, -81.501, 0);
}

But really, be a man and copy it:

template<std::size_t N>
constexpr WPTEntry makeWPTEntry(
            char const (&name)[N],
            double aLatDeg, double aLatMin, double aLonDeg,
            double aLonMin, char bSeven = false,
            double aCourse = 0, double aAzimuth = 0,
            double aDist = 0,
            int aETASecs = 0, int aMod = 0) {
    auto r = WPTEntry{
        bSeven,
        { 0 },
        (aLatDeg + aLatMin) / 60.0,
        (aLonDeg + aLonMin) / 60.0,
        aCourse, aAzimuth,
        aDist, aETASecs, aMod
    };
    for (size_t i = 0; i < N; ++i) {
        r.name[i] = name[i];
    }
    return r;
}

int main() {
    constexpr auto wpt = makeWPTEntry("abc", -24.499, 0, -81.501, 0);
    std::cout << wpt.name;
}


来源:https://stackoverflow.com/questions/62491755/constexpr-construction-of-a-pod-struct-with-a-char-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!