3

我试图以结构化的方式(即使用类)表示一些元信息。它只是标题,我需要支持 c++11,所以不能使用内联变量。我提出了几个潜在的解决方案,但每个都有其缺点。任何建议都将不胜感激,尽管只是指出如何使“替代 B”编译对我来说是一个很好的解决方案。

SthInfo::fieldA用作模板的参数,Processor<Type>::work(field)其中:

  • 检查“容器类型”是否与该处理器匹配
  • 并将 ID 与其他不相关的参数一起使用做一些内部逻辑

备选方案 A - 有效但模板化的 ID

#include <type_traits>

template <typename Container, int ID>
class FieldInfo {
public:
    static constexpr int id = ID;
};

template <typename T>
class Processor {
public:
    template <typename Container, int ID>
    void work(FieldInfo<Container, ID> field) {
        static_assert(std::is_same<Container, T>::value, "Given field can't be processed - container type mismatch");
        // some business logic using the ID, i.e. accessing `field.id`
        int id = field.id;
    }
};

struct Sth {/* contains fieldA and fieldB - just as an example */};

// SthInfo holds meta-information about fields in Sth
struct SthInfo {
    static constexpr FieldInfo<Sth, 1> fieldA{};
};

int main() {
    Processor<Sth> processor;
    processor.work(SthInfo::fieldA);
}

这在 Linux 和 Windows 上可以正常工作(编译和链接)。但是,有没有办法避免ID模板中的常量并将其作为FieldInfo类中的字段?还有其他改进的想法吗?

备选方案 B - 损坏 - 不会链接

我尝试更改为以下代码,但它没有在 Linux 上链接(但在 Windows 上...)undefined reference to SthInfo::fieldA

#include <type_traits>

template <typename Container>
class FieldInfo {
public:
    const int id;
};

template <typename T>
class Processor {
public:
    template <typename Container>
    void work(FieldInfo<Container> field) {
        static_assert(std::is_same<Container, T>::value, "Given field can't be processed - container type mismatch");
        // some business logic using the ID, i.e. accessing `field.id`
        int id = field.id;
    }
};

struct Sth {/* contains fieldA and fieldB - just as an example */};

// SthInfo holds meta-information about fields in Sth
struct SthInfo {
    static constexpr FieldInfo<Sth> fieldA{1};
};

int main() {
    Processor<Sth> processor;
    processor.work(SthInfo::fieldA);
}

替代 C - constexpr 函数 - 不太好用。

更改SthInfo::fieldA为 constexpr 函数会有所帮助,但是()在应用程序代码中使用时必须使用...

#include <type_traits>

template <typename Container>
class FieldInfo {
public:
    const int id;
};

template <typename T>
class Processor {
public:
    template <typename Container>
    void work(FieldInfo<Container> field) {
        static_assert(std::is_same<Container, T>::value, "Given field can't be processed - container type mismatch");
        // some business logic using the ID, i.e. accessing `field.id`
        int id = field.id;
    }
};

struct Sth {/* contains fieldA and fieldB - just as an example */};

// SthInfo holds meta-information about fields in Sth
struct SthInfo {
    static constexpr FieldInfo<Sth> fieldA() { return FieldInfo<Sth>{1}; }
};

int main() {
    Processor<Sth> processor;
    processor.work(SthInfo::fieldA());
}
4

1 回答 1

1

在 C++17 之前,它引入了内联变量——并使 constexpr 静态成员变量隐式内联——如果它们被 odr 使用,则必须在类之外定义这些变量:

const FieldInfo<Sth> SthInfo::fieldA;

请注意,这是一个非模板变量,因此必须在一个源文件中定义。模板化变量的类似定义可以出现在头文件中(使用与内联变量相同的编译器/链接器支持),因此您需要使用类似

template<class T>
struct Info {
    static constexpr FieldInfo<T> fieldA{1};
};
template<class T> const FieldInfo<T> Info<T>::fieldA;
于 2020-07-03T19:31:21.847 回答