具有 char[] 字段的 POD 结构的 constexpr 构造

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

如何实现下面的功能constexpr

这是我用来创建 POD 结构的函数,该结构在我无法更改的“C”头文件中定义。

我最终使用以下静态函数助手(有效)来制作这些结构,我相信它不是 constexpr,因为 strncpy 调用违反了 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;
}

我正在努力按照以下几行(constexpr)做一些事情 - 但是我真的需要带有 const char* name 参数的非 constexpr 函数签名,不幸的是,我不知道如何将此 const char* 内联转换为固定大小的数组 char const (&name)[SIZ_WAYPOINT_NAME] 以与结构字段的构造函数兼容。

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

WPTEntry是一个简单的外部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;

我创建这些结构的方式如下:

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

我之前问过类似的问题question,但是我从来没有得到答案。

我从 this site 中找到了以下内容,但我不确定如何使用它来调整我的参数,也许它可能有用。

struct ArrayWrapper
{
   char const *address_;
   size_t      length_;

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

经过一番折腾 std::integer_sequence 我明白了:

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

但真的,做人,抄袭:

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