在C ++中以在编译时和运行时都可用的方式描述像素格式信息

莫尔夫

我有一个对像素进行操作的库。像素可以采用许多不同的格式。我正在寻找一种有效的方法来描述库API(内部和外部)中的格式。

对于某些类,像素格式是模板参数,对于其他类,它是运行时参数因此,像素格式需要在运行时(作为构造函数或函数参数)和编译时(作为模板参数)均可用。我只想描述一次像素格式

我现在所拥有的是这样的:

enum class color_space : uint8_t { rgb, cmyk /* , etc... */ };

struct pixel_layout {
    color_space space;
    uint8_t channels;
    /* etc... */
};

template <color_space ColorSpace, uint8_t Channels /* etc.. */>
struct pixel_type {
    static constexpr color_space space = ColorSpace;
    static constexpr uint8_t channels = Channels;
    /* etc... */

    static constexpr pixel_layout layout() {
        return {space, channels /* , etc... */ };
    }
};

struct rgb  : public pixel_type<color_space::rgb, 3 /* , etc... */ > {};
struct rgba : public pixel_type<color_space::rgb, 4 /* , etc... */ > {};

这工作得很好。我可以将它们用作运行时并编译时间参数:

template <class PixelType>
class image { };

struct transform {
    transform(const pixel_layout from, const pixel_layout to)
        : from(from), to(to) { /* ... */ }

    pixel_layout from;
    pixel_layout to;
};

还将编译时类型转换为运行时类型:

transform(rgb::layout(), rgba::layout());

但是pixel_layout每当在运行时使用像素类型时,复制并存储它们的细节对我来说都是愚蠢的。从概念上讲,程序所需要的只是对特定对象的ID /地址/引用,pixel_type以及在编译时和运行时检索相关属性(颜色空间,通道等)的方式。

另外,如果我想从像素类型中获取派生的属性,则要pixel_layout避免重复逻辑,就需要对其进行实现然后要在编译时使用它,我需要从pixel_type<...>类到pixel_layout实例再到派生属性。那也似乎有点愚蠢。

我可以避免传递pixel_layout细节,而是使用对pixel_type<...>(子)类的某种引用吗?

我尝试使用enums,因为枚举用作模板参数和函数参数。但是我很难以rgba一种惯用的C ++方式在运行时和编译时从枚举值(例如)变成像素类型属性(例如4个通道)。

同样,枚举作为模板参数在编译错误期间给出的有用诊断要少得多。例如,我得到image<(pixel_type)2>而不是image<rgba>使用clang编译错误消息。因此,这似乎不是一种有用的方法。

特伦

使用非类型引用模板参数可能是一种解决方案。请参阅http://en.cppreference.com/w/cpp/language/template_parameters例如这样:

#include <iostream>
#include <cstdint>
#include <array>

enum class color_space : std::uint8_t { rgb, cymk, other };

// PIXEL LAYOUT
// Can be created/modified at runtime, but a predefined set of pixel_layouts
// exists for compile-time use.
struct pixel_layout {
    color_space space;
    std::uint8_t channels;
};

constexpr bool operator==(const pixel_layout& a, const pixel_layout& b) {
    return (a.space == b.space) && (a.channels == b.channels);
}
constexpr bool operator!=(const pixel_layout& a, const pixel_layout& b) {
    return (a.space != b.space) || (a.channels != b.channels);
}

// Predefined pixel_layout instances, for use as template arguments
// As static constexpr members of class, to make sure they have external linkage,
// required for use as reference template arguments.
struct default_pixel_layouts {
    static constexpr pixel_layout rgb{ color_space::rgb, 3 };
    static constexpr pixel_layout cymk{ color_space::cymk, 4 };        
};

// Definitions for the pixel_layouts
constexpr pixel_layout default_pixel_layouts::rgb;
constexpr pixel_layout default_pixel_layouts::cymk;


// PIXEL TYPE
// Takes pixel_layout reference as non-type template argument.
template<const pixel_layout& Layout>
struct pixel {
    static constexpr const pixel_layout& layout = Layout;

    // Because layout is constexpr, can use its members (e.g. channels),
    // for example as template argument.
    // Here size of pixel depends on number of channels in pixel_layout
    std::array<std::uint32_t, layout.channels> data;
};

// RGB and CYMK pixel_types as type aliases
using rgb = pixel<default_pixel_layouts::rgb>;
using cymk = pixel<default_pixel_layouts::cymk>;


// IMAGE
// Takes pixel type as template argument.
template<class PixelType>
class image {
public:
    using pixel_type = PixelType;
};


// TRANSFORM
// Takes pixel_layouts to transform from/to at runtime. Can for with the predefined
// ones, but also with new ones creates at runtime.
class transform {
private:
    const pixel_layout& from_;
    const pixel_layout& to_;

public:
    transform(const pixel_layout& from, const pixel_layout& to) :
    from_(from), to_(to) { }

    // Example: function working on an image
    template<class Image>
    void run(Image& img) {
        // Need to make sure that Image's pixel_layout (compile-time) matches
        // pixel_layout of the transform (runtime).
        if(Image::pixel_type::layout != from_)
            std::cout << "Wrong pixel type on input image" << std::endl;
        else
            std::cout << "transforming..." << std::endl;
    }

};



int main() {
    image<rgb> rgb_img;
    image<cymk> cymk_img;

    // Transform from rgb to cymk
    transform tr(default_pixel_layouts::rgb, default_pixel_layouts::cymk);  
    tr.run(rgb_img); // ok
    tr.run(cymk_img); // error: input to run() must have rgb pixel_layout

    // Creating a new pixel_layout at runtime
    pixel_layout custom_layout = { color_space::other, 10 };
    transform tr2(custom_layout, default_pixel_layouts::cymk);  

    return 0;
}

http://coliru.stacked-crooked.com/a/981e1b03b3b815c5

对于pixel_layout在编译时使用的用例,pixel_layout需要将不同的可用实例实例化为全局静态constexpr对象。

pixel_type然后实例化为不同的类,具体取决于pixel_layout&给定的模板参数。

但是它们仍然可以在运行时使用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在 C++11 中,是否可以在编译时使用运行时甚至编译时限制条件进行 for 循环?

来自分类Dev

在编译时在C ++元编程中使用运行时参数(变量)

来自分类Dev

C#中的运行时类型与编译时类型

来自分类Dev

C#中的运行时类型与编译时类型

来自分类Dev

C ++中运行时和编译时多态之间的区别

来自分类Dev

c#中.GetType()和Typeof()在运行时或编译时得到解析的重要性

来自分类Dev

当我在Dev C ++中编译和运行时,程序崩溃

来自分类Dev

C ++在编译时将图像像素嵌入矢量中吗?

来自分类Dev

分析时间时C ++中的运行时错误

来自分类Dev

循环和运行时错误中的C ++变量声明

来自分类Dev

C ++中的指针和运行时错误

来自分类Dev

C ++模板和运行时

来自分类Dev

T4在C#中的运行时期间运行或编译tt文件

来自分类Dev

使用g ++编译Objective-C项目时出现运行时错误

来自分类Dev

在Windows中运行时,c ++中的enum类无法在Mac中编译

来自分类Dev

使C ++运行时可用于Elastic Beanstalk部署

来自分类Dev

允许运行时和编译时多态的灵活方式?

来自分类Dev

C中的运行时错误(CodeChef)

来自分类Dev

C ++中运行时的分段错误

来自分类Dev

C中奇怪的运行时错误?

来自分类Dev

C ++中的运行时错误

来自分类Dev

C ++代码中的运行时错误

来自分类Dev

代码C ++中的运行时错误

来自分类Dev

在没有MSVCRT运行时的情况下在Visual Studio 2012中编译C

来自分类Dev

在Qt Creator与命令行中编译C ++项目-生成的.exe不同的运行时

来自分类Dev

您如何在编译时访问有关值的运行时类型的信息?

来自分类Dev

C ++ 11自动编译时间或运行时?

来自分类Dev

使用CSharpCodeProvider进行C#运行时编译

来自分类Dev

C ++ 11自动编译时间或运行时?

Related 相关文章

  1. 1

    在 C++11 中,是否可以在编译时使用运行时甚至编译时限制条件进行 for 循环?

  2. 2

    在编译时在C ++元编程中使用运行时参数(变量)

  3. 3

    C#中的运行时类型与编译时类型

  4. 4

    C#中的运行时类型与编译时类型

  5. 5

    C ++中运行时和编译时多态之间的区别

  6. 6

    c#中.GetType()和Typeof()在运行时或编译时得到解析的重要性

  7. 7

    当我在Dev C ++中编译和运行时,程序崩溃

  8. 8

    C ++在编译时将图像像素嵌入矢量中吗?

  9. 9

    分析时间时C ++中的运行时错误

  10. 10

    循环和运行时错误中的C ++变量声明

  11. 11

    C ++中的指针和运行时错误

  12. 12

    C ++模板和运行时

  13. 13

    T4在C#中的运行时期间运行或编译tt文件

  14. 14

    使用g ++编译Objective-C项目时出现运行时错误

  15. 15

    在Windows中运行时,c ++中的enum类无法在Mac中编译

  16. 16

    使C ++运行时可用于Elastic Beanstalk部署

  17. 17

    允许运行时和编译时多态的灵活方式?

  18. 18

    C中的运行时错误(CodeChef)

  19. 19

    C ++中运行时的分段错误

  20. 20

    C中奇怪的运行时错误?

  21. 21

    C ++中的运行时错误

  22. 22

    C ++代码中的运行时错误

  23. 23

    代码C ++中的运行时错误

  24. 24

    在没有MSVCRT运行时的情况下在Visual Studio 2012中编译C

  25. 25

    在Qt Creator与命令行中编译C ++项目-生成的.exe不同的运行时

  26. 26

    您如何在编译时访问有关值的运行时类型的信息?

  27. 27

    C ++ 11自动编译时间或运行时?

  28. 28

    使用CSharpCodeProvider进行C#运行时编译

  29. 29

    C ++ 11自动编译时间或运行时?

热门标签

归档